summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.cvsignore5
-rw-r--r--src/Makefile.am26
-rw-r--r--src/actions.cc351
-rw-r--r--src/actions.hh79
-rw-r--r--src/bindings.cc655
-rw-r--r--src/bindings.hh186
-rw-r--r--src/client.cc2014
-rw-r--r--src/client.hh759
-rw-r--r--src/config.cc61
-rw-r--r--src/config.hh14
-rw-r--r--src/frame.cc959
-rw-r--r--src/frame.hh203
-rw-r--r--src/gettext.h70
-rw-r--r--src/main.cc51
-rw-r--r--src/openbox.cc413
-rw-r--r--src/openbox.hh250
-rw-r--r--src/python.cc141
-rw-r--r--src/python.hh243
-rw-r--r--src/screen.cc945
-rw-r--r--src/screen.hh230
20 files changed, 0 insertions, 7655 deletions
diff --git a/src/.cvsignore b/src/.cvsignore
deleted file mode 100644
index 48bb3aad..00000000
--- a/src/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-Makefile
-Makefile.in
-openbox3
-.deps
-.libs
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 107f7355..00000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-localedir=$(datadir)/locale
-scriptdir = $(libdir)/openbox/python
-DEFAULT_MENU=$(pkgdatadir)/menu
-DEFAULT_STYLE=$(pkgdatadir)/styles/mbdtex
-
-CPPFLAGS=$(XFT_CFLAGS) $(PYTHON_CFLAGS) @CPPFLAGS@ \
--DDEFAULTMENU=\"$(DEFAULT_MENU)\" \
--DDEFAULTSTYLE=\"$(DEFAULT_STYLE)\" \
--DLOCALEDIR=\"$(localedir)\" \
--DSCRIPTDIR=\"$(scriptdir)\"
-
-LIBS=$(XFT_LIBS) $(PYTHON_LIBS) @LIBS@ $(SWIG_PYTHON_LIB)
-
-bin_PROGRAMS= openbox3
-
-openbox3_LDADD=-L../otk -lotk @LIBINTL@
-openbox3_LDFLAGS=-export-dynamic
-openbox3_SOURCES= actions.cc client.cc frame.cc openbox.cc screen.cc \
- main.cc python.cc bindings.cc config.cc
-noinst_HEADERS= actions.hh bindings.hh client.hh frame.hh openbox.hh \
- python.hh screen.hh config.hh
-
-MAINTAINERCLEANFILES= Makefile.in
-
-distclean-local:
- $(RM) *\~ *.orig *.rej .\#*
diff --git a/src/actions.cc b/src/actions.cc
deleted file mode 100644
index 36b4f111..00000000
--- a/src/actions.cc
+++ /dev/null
@@ -1,351 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#include "config.h"
-
-#include "actions.hh"
-#include "openbox.hh"
-#include "client.hh"
-#include "frame.hh"
-#include "screen.hh"
-#include "python.hh"
-#include "bindings.hh"
-#include "otk/display.hh"
-
-#include <cstdio>
-#include <algorithm>
-
-namespace ob {
-
-Actions::Actions()
- : _dragging(false)
-{
-}
-
-
-Actions::~Actions()
-{
-}
-
-
-void Actions::buttonPressHandler(const XButtonEvent &e)
-{
- otk::EventHandler::buttonPressHandler(e);
-
- MouseContext::MC context;
- EventHandler *h = openbox->findHandler(e.window);
- Frame *f = dynamic_cast<Frame*>(h);
- if (f)
- context= f->mouseContext(e.window);
- else if (dynamic_cast<Client*>(h))
- context = MouseContext::Window;
- else if (dynamic_cast<Screen*>(h))
- context = MouseContext::Root;
- else
- return; // not a valid mouse context
-
- if (_press.button) {
- unsigned int mask;
- switch(_press.button) {
- case Button1: mask = Button1Mask; break;
- case Button2: mask = Button2Mask; break;
- case Button3: mask = Button3Mask; break;
- case Button4: mask = Button4Mask; break;
- case Button5: mask = Button5Mask; break;
- default: mask = 0; // on other buttons we have to assume its not pressed...
- }
- // was the button released but we didnt get the event? (pointergrabs cause
- // this)
- if (!(e.state & mask))
- _press.button = 0;
- }
-
- // run the PRESS python hook
- // kill off the Button1Mask etc, only want the modifiers
- unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask |
- Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
- int screen;
- Client *c = openbox->findClient(e.window);
- if (c)
- screen = c->screen();
- else
- screen = otk::display->findScreen(e.root)->screen();
- MouseData data(screen, c, e.time, state, e.button, context,
- MouseAction::Press);
- openbox->bindings()->fireButton(&data);
-
- if (_press.button) return; // won't count toward CLICK events
-
- _press.win = e.window;
- _press.button = e.button;
- _press.pos = otk::Point(e.x_root, e.y_root);
- if (c)
- _press.clientarea = c->area();
-
- printf("press queue %u pressed %u\n", _press.button, e.button);
-
- if (context == MouseContext::Window) {
- /*
- Because of how events are grabbed on the client window, we can't get
- ButtonRelease events, so instead we simply manufacture them here, so that
- clicks/doubleclicks etc still work.
- */
- //XButtonEvent ev = e;
- //ev.type = ButtonRelease;
- buttonReleaseHandler(e);
- }
-}
-
-
-void Actions::buttonReleaseHandler(const XButtonEvent &e)
-{
- otk::EventHandler::buttonReleaseHandler(e);
-
- MouseContext::MC context;
- EventHandler *h = openbox->findHandler(e.window);
- Frame *f = dynamic_cast<Frame*>(h);
- if (f)
- context= f->mouseContext(e.window);
- else if (dynamic_cast<Client*>(h))
- context = MouseContext::Window;
- else if (dynamic_cast<Screen*>(h))
- context = MouseContext::Root;
- else
- return; // not a valid mouse context
-
- // run the RELEASE python hook
- // kill off the Button1Mask etc, only want the modifiers
- unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask |
- Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
- int screen;
- Client *c = openbox->findClient(e.window);
- if (c)
- screen = c->screen();
- else
- screen = otk::display->findScreen(e.root)->screen();
- MouseData data(screen, c, e.time, state, e.button, context,
- MouseAction::Release);
- openbox->bindings()->fireButton(&data);
-
- // not for the button we're watching?
- if (_press.button != e.button) return;
-
- _press.button = 0;
- _dragging = false;
-
- // find the area of the window
- XWindowAttributes attr;
- if (!XGetWindowAttributes(**otk::display, e.window, &attr)) return;
-
- // if not on the window any more, it isnt a CLICK
- if (!(e.same_screen && e.x >= 0 && e.y >= 0 &&
- e.x < attr.width && e.y < attr.height))
- return;
-
- // run the CLICK python hook
- data.action = MouseAction::Click;
- openbox->bindings()->fireButton(&data);
-
- long dblclick = 0;
- python_get_long("double_click_delay", &dblclick);
- if (e.time - _release.time < (unsigned)dblclick &&
- _release.win == e.window && _release.button == e.button) {
-
- // run the DOUBLECLICK python hook
- data.action = MouseAction::DoubleClick;
- openbox->bindings()->fireButton(&data);
-
- // reset so you cant triple click for 2 doubleclicks
- _release.win = 0;
- _release.button = 0;
- _release.time = 0;
- } else {
- // save the button release, might be part of a double click
- _release.win = e.window;
- _release.button = e.button;
- _release.time = e.time;
- }
-}
-
-
-void Actions::enterHandler(const XCrossingEvent &e)
-{
- otk::EventHandler::enterHandler(e);
-
- // run the ENTER python hook
- int screen;
- Client *c = openbox->findClient(e.window);
- if (c)
- screen = c->screen();
- else
- screen = otk::display->findScreen(e.root)->screen();
- EventData data(screen, c, EventAction::EnterWindow, e.state);
- openbox->bindings()->fireEvent(&data);
-}
-
-
-void Actions::leaveHandler(const XCrossingEvent &e)
-{
- otk::EventHandler::leaveHandler(e);
-
- // run the LEAVE python hook
- int screen;
- Client *c = openbox->findClient(e.window);
- if (c)
- screen = c->screen();
- else
- screen = otk::display->findScreen(e.root)->screen();
- EventData data(screen, c, EventAction::LeaveWindow, e.state);
- openbox->bindings()->fireEvent(&data);
-}
-
-
-void Actions::keyPressHandler(const XKeyEvent &e)
-{
- otk::EventHandler::keyPressHandler(e);
-
- // kill off the Button1Mask etc, only want the modifiers
- unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask |
- Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
-
- // add to the state the mask of the modifier being pressed, if it is
- // a modifier key being pressed (this is a little ugly..)
- const XModifierKeymap *map = otk::display->modifierMap();
- const int mask_table[] = {
- ShiftMask, LockMask, ControlMask, Mod1Mask,
- Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
- };
- KeyCode *kp = map->modifiermap;
- for (int i = 0, n = sizeof(mask_table)/sizeof(mask_table[0]); i < n; ++i) {
- for (int k = 0; k < map->max_keypermod; ++k) {
- if (*kp == e.keycode) { // found the keycode
- state |= mask_table[i]; // add the mask for it
- i = n; // cause the first loop to break;
- break; // get outta here!
- }
- ++kp;
- }
- }
-
- openbox->bindings()->
- fireKey(otk::display->findScreen(e.root)->screen(),
- state, e.keycode, e.time, KeyAction::Press);
-}
-
-
-void Actions::keyReleaseHandler(const XKeyEvent &e)
-{
- otk::EventHandler::keyReleaseHandler(e);
-
- // kill off the Button1Mask etc, only want the modifiers
- unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask |
- Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
-
- // remove from the state the mask of the modifier being released, if it is
- // a modifier key being released (this is a little ugly..)
- const XModifierKeymap *map = otk::display->modifierMap();
- const int mask_table[] = {
- ShiftMask, LockMask, ControlMask, Mod1Mask,
- Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
- };
- KeyCode *kp = map->modifiermap;
- for (int i = 0, n = sizeof(mask_table)/sizeof(mask_table[0]); i < n; ++i) {
- for (int k = 0; k < map->max_keypermod; ++k) {
- if (*kp == e.keycode) { // found the keycode
- state &= ~mask_table[i]; // remove the mask for it
- i = n; // cause the first loop to break;
- break; // get outta here!
- }
- ++kp;
- }
- }
-
- openbox->bindings()->
- fireKey(otk::display->findScreen(e.root)->screen(),
- state, e.keycode, e.time, KeyAction::Release);
-}
-
-
-void Actions::motionHandler(const XMotionEvent &e)
-{
- otk::EventHandler::motionHandler(e);
-
- if (!e.same_screen) return; // this just gets stupid
-
- if (e.window != _press.win) return;
-
- MouseContext::MC context;
- EventHandler *h = openbox->findHandler(e.window);
- Frame *f = dynamic_cast<Frame*>(h);
- if (f)
- context= f->mouseContext(e.window);
- else if (dynamic_cast<Client*>(h))
- context = MouseContext::Window;
- else if (dynamic_cast<Screen*>(h))
- context = MouseContext::Root;
- else
- return; // not a valid mouse context
-
- int x_root = e.x_root, y_root = e.y_root;
-
- // compress changes to a window into a single change
- XEvent ce;
- while (XCheckTypedWindowEvent(**otk::display, e.window, e.type, &ce)) {
- x_root = ce.x_root;
- y_root = ce.y_root;
- }
-
- int screen;
- Client *c = openbox->findClient(e.window);
- if (c)
- screen = c->screen();
- else
- screen = otk::display->findScreen(e.root)->screen();
-
- if (!_dragging) {
- int dx = x_root - _press.pos.x();
- int dy = y_root - _press.pos.y();
- long threshold = 0;
- python_get_long("drag_threshold", &threshold);
- if (!(std::abs(dx) >= threshold || std::abs(dy) >= threshold))
- return; // not at the threshold yet
- }
- _dragging = true; // in a drag now
-
- // check if the movement is more than the threshold
-
- // run the MOTION python hook
- // kill off the Button1Mask etc, only want the modifiers
- unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask |
- Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
- unsigned int button = _press.button;
- MouseData data(screen, c, e.time, state, button, context,
- MouseAction::Motion, x_root, y_root,
- _press.pos, _press.clientarea);
- openbox->bindings()->fireButton(&data);
-}
-
-#ifdef XKB
-void Actions::xkbHandler(const XkbEvent &e)
-{
- Window w;
- int screen;
-
- otk::EventHandler::xkbHandler(e);
-
- switch (((XkbAnyEvent*)&e)->xkb_type) {
- case XkbBellNotify:
- w = ((XkbBellNotifyEvent*)&e)->window;
- Client *c = openbox->findClient(w);
- if (c)
- screen = c->screen();
- else
- screen = openbox->focusedScreen()->number();
- EventData data(screen, c, EventAction::Bell, 0);
- openbox->bindings()->fireEvent(&data);
- break;
- }
-}
-#endif // XKB
-
-}
-
diff --git a/src/actions.hh b/src/actions.hh
deleted file mode 100644
index 4165dd2e..00000000
--- a/src/actions.hh
+++ /dev/null
@@ -1,79 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef __actions_hh
-#define __actions_hh
-
-/*! @file actions.hh
- @brief The action interface for user-available actions
-*/
-
-#include "otk/point.hh"
-#include "otk/rect.hh"
-#include "otk/eventhandler.hh"
-
-extern "C" {
-#include <X11/Xlib.h>
-#include <Python.h>
-}
-
-#include <map>
-
-namespace ob {
-
-//! The action interface for user-available actions
-/*!
- When these actions are fired, hooks to the guile engine are fired so that
- guile code is run.
-*/
-class Actions : public otk::EventHandler {
-public:
-#ifndef SWIG // get rid of a swig warning
- struct ButtonReleaseAction {
- Window win;
- unsigned int button;
- Time time;
- ButtonReleaseAction() { win = 0; button = 0; time = 0; }
- };
-
- struct ButtonPressAction {
- Window win;
- unsigned int button;
- otk::Point pos;
- otk::Rect clientarea;
- ButtonPressAction() { button = 0; }
- };
-#endif // SWIG
-private:
- //! The last button release processed for CLICKs
- ButtonReleaseAction _release;
- //! The last button press processed for CLICKs
- ButtonPressAction _press;
- //! This is set to true once a drag has started and false when done to make
- //! sure the threshold isnt checked anymore once a drag is underway
- bool _dragging;
-
-public:
- //! Constructs an Actions object
- Actions();
- //! Destroys the Actions object
- virtual ~Actions();
-
- virtual void buttonPressHandler(const XButtonEvent &e);
- virtual void buttonReleaseHandler(const XButtonEvent &e);
-
- virtual void enterHandler(const XCrossingEvent &e);
- virtual void leaveHandler(const XCrossingEvent &e);
-
- virtual void keyPressHandler(const XKeyEvent &e);
- virtual void keyReleaseHandler(const XKeyEvent &e);
-
- virtual void motionHandler(const XMotionEvent &e);
-
-#ifdef XKB
- virtual void xkbHandler(const XkbEvent &e);
-#endif // XKB
-
-};
-
-}
-
-#endif // __actions_hh
diff --git a/src/bindings.cc b/src/bindings.cc
deleted file mode 100644
index e6f98f79..00000000
--- a/src/bindings.cc
+++ /dev/null
@@ -1,655 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#include "config.h"
-
-#include "bindings.hh"
-#include "screen.hh"
-#include "openbox.hh"
-#include "client.hh"
-#include "frame.hh"
-#include "otk/display.hh"
-
-extern "C" {
-#include <X11/Xlib.h>
-
-#include "gettext.h"
-#define _(str) gettext(str)
-}
-
-#include <cstdlib>
-#include <algorithm>
-
-namespace ob {
-
-static bool buttonvalue(const std::string &button, unsigned int *val)
-{
- if (button == "Left")
- *val = 1;
- else if (button == "Middle")
- *val = 2;
- else if (button == "Right")
- *val = 3;
- else if (button == "Up")
- *val = 4;
- else if (button == "Down")
- *val = 5;
- else {
- // try convert to number
- int i = atoi(button.c_str());
- if (i <= 0)
- return false;
- *val = i;
- }
- return true;
-}
-
-static bool modvalue(const std::string &mod, unsigned int *val)
-{
- if (mod == "C") { // control
- *val |= ControlMask;
- } else if (mod == "S") { // shift
- *val |= ShiftMask;
- } else if (mod == "A" || // alt/mod1
- mod == "M" ||
- mod == "Mod1" ||
- mod == "M1") {
- *val |= Mod1Mask;
- } else if (mod == "Mod2" || // mod2
- mod == "M2") {
- *val |= Mod2Mask;
- } else if (mod == "Mod3" || // mod3
- mod == "M3") {
- *val |= Mod3Mask;
- } else if (mod == "W" || // windows/mod4
- mod == "Mod4" ||
- mod == "M4") {
- *val |= Mod4Mask;
- } else if (mod == "Mod5" || // mod5
- mod == "M5") {
- *val |= Mod5Mask;
- } else { // invalid
- return false;
- }
- return true;
-}
-
-bool Bindings::translate(const std::string &str, Binding &b,bool askey) const
-{
- // parse out the base key name
- std::string::size_type keybegin = str.find_last_of('-');
- keybegin = (keybegin == std::string::npos) ? 0 : keybegin + 1;
- std::string key(str, keybegin);
-
- // parse out the requested modifier keys
- unsigned int modval = 0;
- std::string::size_type begin = 0, end;
- while (begin != keybegin) {
- end = str.find_first_of('-', begin);
-
- std::string mod(str, begin, end-begin);
- if (!modvalue(mod, &modval)) {
- printf(_("Invalid modifier element in key binding: %s\n"), mod.c_str());
- return false;
- }
-
- begin = end + 1;
- }
-
- // set the binding
- b.modifiers = modval;
- if (askey) {
- KeySym sym = XStringToKeysym(const_cast<char *>(key.c_str()));
- if (sym == NoSymbol) {
- printf(_("Invalid Key name in key binding: %s\n"), key.c_str());
- return false;
- }
- if (!(b.key = XKeysymToKeycode(**otk::display, sym)))
- printf(_("No valid keycode for Key in key binding: %s\n"), key.c_str());
- return b.key != 0;
- } else {
- return buttonvalue(key, &b.key);
- }
-}
-
-static void destroytree(KeyBindingTree *tree)
-{
- while (tree) {
- KeyBindingTree *c = tree->first_child;
- delete tree;
- tree = c;
- }
-}
-
-KeyBindingTree *Bindings::buildtree(const StringVect &keylist,
- KeyCallback callback, void *data) const
-{
- if (keylist.empty()) return 0; // nothing in the list.. return 0
-
- KeyBindingTree *ret = 0, *p;
-
- StringVect::const_reverse_iterator it, end = keylist.rend();
- for (it = keylist.rbegin(); it != end; ++it) {
- p = ret;
- ret = new KeyBindingTree();
- if (!p) {
- // this is the first built node, the bottom node of the tree
- ret->chain = false;
- ret->callbacks.push_back(KeyCallbackData(callback, data));
- }
- ret->first_child = p;
- if (!translate(*it, ret->binding)) {
- destroytree(ret);
- ret = 0;
- break;
- }
- }
- return ret;
-}
-
-
-Bindings::Bindings()
- : _curpos(&_keytree),
- _resetkey(0,0),
- _timer((otk::Timer *) 0),
- _keybgrab_callback(0, 0),
- _grabbed(0)
-{
- setResetKey("C-g"); // set the default reset key
-}
-
-
-Bindings::~Bindings()
-{
- if (_timer)
- delete _timer;
- if (_grabbed) {
- _grabbed = false;
- XUngrabKeyboard(**otk::display, CurrentTime);
- }
- removeAllKeys();
- //removeAllButtons(); // this is done by each client as they are unmanaged
- removeAllEvents();
-}
-
-
-void Bindings::assimilate(KeyBindingTree *node)
-{
- KeyBindingTree *a, *b, *tmp, *last;
-
- if (!_keytree.first_child) {
- // there are no nodes at this level yet
- _keytree.first_child = node;
- } else {
- a = _keytree.first_child;
- last = a;
- b = node;
- while (a) {
- last = a;
- if (a->binding != b->binding) {
- a = a->next_sibling;
- } else {
- tmp = b;
- b = b->first_child;
- delete tmp;
- a = a->first_child;
- }
- }
- if (last->binding != b->binding)
- last->next_sibling = b;
- else {
- last->first_child = b->first_child;
- delete b;
- }
- }
-}
-
-
-KeyBindingTree *Bindings::find(KeyBindingTree *search,
- bool *conflict) const {
- *conflict = false;
- KeyBindingTree *a, *b;
- a = _keytree.first_child;
- b = search;
- while (a && b) {
- if (a->binding != b->binding) {
- a = a->next_sibling;
- } else {
- if (a->chain == b->chain) {
- if (!a->chain) {
- // found it! (return the actual id, not the search's)
- return a;
- }
- } else {
- *conflict = true;
- return 0; // the chain status' don't match (conflict!)
- }
- b = b->first_child;
- a = a->first_child;
- }
- }
- return 0; // it just isn't in here
-}
-
-
-bool Bindings::addKey(const StringVect &keylist, KeyCallback callback,
- void *data)
-{
- KeyBindingTree *tree, *t;
- bool conflict;
-
- if (!(tree = buildtree(keylist, callback, data)))
- return false; // invalid binding requested
-
- t = find(tree, &conflict);
- if (conflict) {
- // conflicts with another binding
- destroytree(tree);
- return false;
- }
-
- if (t) {
- // already bound to something
- t->callbacks.push_back(KeyCallbackData(callback, data));
- destroytree(tree);
- } else {
- // grab the server here to make sure no key pressed go missed
- otk::display->grab();
- grabKeys(false);
-
- // assimilate this built tree into the main tree
- assimilate(tree); // assimilation destroys/uses the tree
-
- grabKeys(true);
- otk::display->ungrab();
- }
-
- return true;
-}
-
-/*
-bool Bindings::removeKey(const StringVect &keylist, KeyCallback callback, void *data)
-{
- assert(false); // XXX: function not implemented yet
-
- KeyBindingTree *tree;
- bool conflict;
-
- if (!(tree = buildtree(keylist, 0)))
- return false; // invalid binding requested
-
- KeyBindingTree *t = find(tree, &conflict);
- if (t) {
- KeyCallbackList::iterator it = std::find(t->callbacks.begin(),
- t->callbacks.end(),
- callback);
- if (it != t->callbacks.end()) {
- // grab the server here to make sure no key pressed go missed
- otk::display->grab();
- grabKeys(false);
-
- _curpos = &_keytree;
-
- // XXX do shit here ...
- Py_XDECREF(*it);
-
- grabKeys(true);
- otk::display->ungrab();
-
- return true;
- }
- }
- return false;
-}
-*/
-
-void Bindings::setResetKey(const std::string &key)
-{
- Binding b(0, 0);
- if (translate(key, b)) {
- _resetkey.key = b.key;
- _resetkey.modifiers = b.modifiers;
- }
-}
-
-
-static void remove_branch(KeyBindingTree *first)
-{
- KeyBindingTree *p = first;
-
- while (p) {
- if (p->first_child)
- remove_branch(p->first_child);
- KeyBindingTree *s = p->next_sibling;
- while(!p->callbacks.empty()) {
- p->callbacks.pop_front();
- }
- delete p;
- p = s;
- }
-}
-
-
-void Bindings::removeAllKeys()
-{
- grabKeys(false);
- if (_keytree.first_child) {
- remove_branch(_keytree.first_child);
- _keytree.first_child = 0;
- }
- grabKeys(true);
-}
-
-
-void Bindings::grabKeys(bool grab)
-{
- for (int i = 0; i < ScreenCount(**otk::display); ++i) {
- Screen *sc = openbox->screen(i);
- if (!sc) continue; // not a managed screen
- Window root = otk::display->screenInfo(i)->rootWindow();
- if (!grab) {
- otk::display->ungrabAllKeys(root);
- continue;
- }
- KeyBindingTree *p = _keytree.first_child;
- while (p) {
- otk::display->grabKey(p->binding.key, p->binding.modifiers,
- root, false, GrabModeAsync, GrabModeSync,
- false);
- p = p->next_sibling;
- }
- }
-}
-
-
-bool Bindings::grabKeyboard(int screen, KeyCallback callback, void *data)
-{
- assert(callback);
- if (_keybgrab_callback.callback) return false; // already grabbed
-
- if (!openbox->screen(screen))
- return false; // the screen is not managed
-
- Window root = otk::display->screenInfo(screen)->rootWindow();
- if (XGrabKeyboard(**otk::display, root, false, GrabModeAsync,
- GrabModeAsync, CurrentTime))
- return false;
- _keybgrab_callback.callback = callback;
- _keybgrab_callback.data = data;
- return true;
-}
-
-
-void Bindings::ungrabKeyboard()
-{
- if (!_keybgrab_callback.callback) return; // not grabbed
-
- _keybgrab_callback = KeyCallbackData(0, 0);
- if (!_grabbed) /* don't release out from under keychains */
- XUngrabKeyboard(**otk::display, CurrentTime);
- XUngrabPointer(**otk::display, CurrentTime);
-}
-
-
-bool Bindings::grabPointer(int screen)
-{
- if (!openbox->screen(screen))
- return false; // the screen is not managed
-
- Window root = otk::display->screenInfo(screen)->rootWindow();
- XGrabPointer(**otk::display, root, false, 0, GrabModeAsync,
- GrabModeAsync, None, None, CurrentTime);
- return true;
-}
-
-
-void Bindings::ungrabPointer()
-{
- XUngrabPointer(**otk::display, CurrentTime);
-}
-
-
-void Bindings::fireKey(int screen, unsigned int modifiers, unsigned int key,
- Time time, KeyAction::KA action)
-{
- if (_keybgrab_callback.callback) {
- Client *c = openbox->focusedClient();
- KeyData data(screen, c, time, modifiers, key, action);
- _keybgrab_callback.fire(&data);
- }
-
- // KeyRelease events only occur during keyboard grabs
- if (action == KeyAction::Release) return;
-
- if (key == _resetkey.key && modifiers == _resetkey.modifiers) {
- resetChains(this);
- XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime);
- } else {
- KeyBindingTree *p = _curpos->first_child;
- while (p) {
- if (p->binding.key == key && p->binding.modifiers == modifiers) {
- if (p->chain) {
- if (_timer)
- delete _timer;
- _timer = new otk::Timer(5000, // 5 second timeout
- (otk::Timer::TimeoutHandler)resetChains,
- this);
- if (!_grabbed && !_keybgrab_callback.callback) {
- Window root = otk::display->screenInfo(screen)->rootWindow();
- //grab should never fail because we should have a sync grab at
- //this point
- XGrabKeyboard(**otk::display, root, 0, GrabModeAsync,
- GrabModeSync, CurrentTime);
- }
- _grabbed = true;
- _curpos = p;
- XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime);
- } else {
- Client *c = openbox->focusedClient();
- KeyData data(screen, c, time, modifiers, key, action);
- KeyCallbackList::iterator it, end = p->callbacks.end();
- for (it = p->callbacks.begin(); it != end; ++it)
- it->fire(&data);
- XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime);
- resetChains(this);
- }
- break;
- }
- p = p->next_sibling;
- }
- }
-}
-
-void Bindings::resetChains(Bindings *self)
-{
- if (self->_timer) {
- delete self->_timer;
- self->_timer = (otk::Timer *) 0;
- }
- self->_curpos = &self->_keytree;
- if (self->_grabbed) {
- self->_grabbed = false;
- if (!self->_keybgrab_callback.callback)
- XUngrabKeyboard(**otk::display, CurrentTime);
- }
-}
-
-
-bool Bindings::addButton(const std::string &but, MouseContext::MC context,
- MouseAction::MA action, MouseCallback callback,
- void *data)
-{
- assert(context >= 0 && context < MouseContext::NUM_MOUSE_CONTEXT);
- assert(action >= 0 && action < MouseAction::NUM_MOUSE_ACTION);
-
- Binding b(0,0);
- if (!translate(but, b, false))
- return false;
-
- ButtonBindingList::iterator it, end = _buttons[context].end();
-
- // look for a duplicate binding
- for (it = _buttons[context].begin(); it != end; ++it)
- if ((*it)->binding.key == b.key &&
- (*it)->binding.modifiers == b.modifiers) {
- break;
- }
-
- ButtonBinding *bind;
-
- // the binding didnt exist yet, add it
- if (it == end) {
- bind = new ButtonBinding();
- bind->binding.key = b.key;
- bind->binding.modifiers = b.modifiers;
- _buttons[context].push_back(bind);
- // grab the button on all clients
- for (int sn = 0; sn < ScreenCount(**otk::display); ++sn) {
- Screen *s = openbox->screen(sn);
- if (!s) continue; // not managed
- Client::List::iterator c_it, c_end = s->clients.end();
- for (c_it = s->clients.begin(); c_it != c_end; ++c_it) {
- grabButton(true, bind->binding, context, *c_it);
- }
- }
- } else
- bind = *it;
- bind->callbacks[action].push_back(MouseCallbackData(callback, data));
- return true;
-}
-
-void Bindings::removeAllButtons()
-{
- for (int i = 0; i < MouseContext::NUM_MOUSE_CONTEXT; ++i) {
- ButtonBindingList::iterator it, end = _buttons[i].end();
- for (it = _buttons[i].begin(); it != end; ++it) {
- for (int a = 0; a < MouseAction::NUM_MOUSE_ACTION; ++a) {
- while (!(*it)->callbacks[a].empty()) {
- (*it)->callbacks[a].pop_front();
- }
- }
- // ungrab the button on all clients
- for (int sn = 0; sn < ScreenCount(**otk::display); ++sn) {
- Screen *s = openbox->screen(sn);
- if (!s) continue; // not managed
- Client::List::iterator c_it, c_end = s->clients.end();
- for (c_it = s->clients.begin(); c_it != c_end; ++c_it) {
- grabButton(false, (*it)->binding, (MouseContext::MC)i, *c_it);
- }
- }
- }
- }
-}
-
-void Bindings::grabButton(bool grab, const Binding &b,
- MouseContext::MC context, Client *client)
-{
- Window win;
- int mode = GrabModeAsync;
- unsigned int mask;
- switch(context) {
- case MouseContext::Frame:
- win = client->frame->window();
- mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
- break;
- case MouseContext::Window:
- win = client->frame->plate();
- mode = GrabModeSync; // this is handled in fireButton
- mask = ButtonPressMask; // can't catch more than this with Sync mode
- // the release event is manufactured by the
- // master buttonPressHandler
- break;
- default:
- // any other elements already get button events, don't grab on them
- return;
- }
- if (grab)
- otk::display->grabButton(b.key, b.modifiers, win, false, mask, mode,
- GrabModeAsync, None, None, false);
- else
- otk::display->ungrabButton(b.key, b.modifiers, win);
-}
-
-void Bindings::grabButtons(bool grab, Client *client)
-{
- for (int i = 0; i < MouseContext::NUM_MOUSE_CONTEXT; ++i) {
- ButtonBindingList::iterator it, end = _buttons[i].end();
- for (it = _buttons[i].begin(); it != end; ++it)
- grabButton(grab, (*it)->binding, (MouseContext::MC)i, client);
- }
-}
-
-void Bindings::fireButton(MouseData *data)
-{
- if (data->context == MouseContext::Window) {
- // Replay the event, so it goes to the client
- XAllowEvents(**otk::display, ReplayPointer, data->time);
- }
-
- ButtonBindingList::iterator it, end = _buttons[data->context].end();
- for (it = _buttons[data->context].begin(); it != end; ++it)
- if ((*it)->binding.key == data->button &&
- (*it)->binding.modifiers == data->state) {
- MouseCallbackList::iterator c_it,
- c_end = (*it)->callbacks[data->action].end();
- for (c_it = (*it)->callbacks[data->action].begin();
- c_it != c_end; ++c_it)
- c_it->fire(data);
- }
-}
-
-
-bool Bindings::addEvent(EventAction::EA action, EventCallback callback,
- void *data)
-{
- if (action < 0 || action >= EventAction::NUM_EVENT_ACTION) {
- return false;
- }
-#ifdef XKB
- if (action == EventAction::Bell && _eventlist[action].empty())
- XkbSelectEvents(**otk::display, XkbUseCoreKbd,
- XkbBellNotifyMask, XkbBellNotifyMask);
-#endif // XKB
- _eventlist[action].push_back(EventCallbackData(callback, data));
- return true;
-}
-
-bool Bindings::removeEvent(EventAction::EA action, EventCallback callback,
- void *data)
-{
- if (action < 0 || action >= EventAction::NUM_EVENT_ACTION) {
- return false;
- }
-
- EventCallbackList::iterator it = std::find(_eventlist[action].begin(),
- _eventlist[action].end(),
- EventCallbackData(callback,
- data));
- if (it != _eventlist[action].end()) {
- _eventlist[action].erase(it);
-#ifdef XKB
- if (action == EventAction::Bell && _eventlist[action].empty())
- XkbSelectEvents(**otk::display, XkbUseCoreKbd,
- XkbBellNotifyMask, 0);
-#endif // XKB
- return true;
- }
- return false;
-}
-
-void Bindings::removeAllEvents()
-{
- for (int i = 0; i < EventAction::NUM_EVENT_ACTION; ++i) {
- while (!_eventlist[i].empty()) {
- _eventlist[i].pop_front();
- }
- }
-}
-
-void Bindings::fireEvent(EventData *data)
-{
- EventCallbackList::iterator c_it, c_end = _eventlist[data->action].end();
- for (c_it = _eventlist[data->action].begin(); c_it != c_end; ++c_it)
- c_it->fire(data);
-}
-
-}
diff --git a/src/bindings.hh b/src/bindings.hh
deleted file mode 100644
index f45e5ca3..00000000
--- a/src/bindings.hh
+++ /dev/null
@@ -1,186 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef __binding_hh
-#define __binding_hh
-
-/*! @file bindings.hh
- @brief I dunno.. some binding stuff?
-*/
-
-#include "actions.hh"
-#include "python.hh"
-#include "otk/timer.hh"
-
-#include <string>
-#include <list>
-#include <vector>
-
-namespace ob {
-
-class Client;
-
-struct MouseCallbackData {
- MouseCallback callback;
- void *data;
- MouseCallbackData(MouseCallback c, void *d) : callback(c), data(d) {}
- void fire(MouseData *d) { callback(d, data); }
- bool operator==(const MouseCallbackData &other) { return (callback ==
- other.callback &&
- data ==
- other.data); }
-};
-
-struct KeyCallbackData {
- KeyCallback callback;
- void *data;
- KeyCallbackData(KeyCallback c, void *d) : callback(c), data(d) {}
- void fire(KeyData *d) { callback(d, data); }
- bool operator==(const KeyCallbackData &other) { return (callback ==
- other.callback &&
- data ==
- other.data); }
-};
-
-struct EventCallbackData {
- EventCallback callback;
- void *data;
- EventCallbackData(EventCallback c, void *d) : callback(c), data(d) {}
- void fire(EventData *d) { callback(d, data); }
- bool operator==(const EventCallbackData &other) { return (callback ==
- other.callback &&
- data ==
- other.data); }
-};
-
-typedef std::list<MouseCallbackData> MouseCallbackList;
-typedef std::list<KeyCallbackData> KeyCallbackList;
-typedef std::list<EventCallbackData> EventCallbackList;
-
-typedef struct Binding {
- unsigned int modifiers;
- unsigned int key;
-
- bool operator==(struct Binding &b2) { return key == b2.key &&
- modifiers == b2.modifiers; }
- bool operator!=(struct Binding &b2) { return key != b2.key ||
- modifiers != b2.modifiers; }
- Binding(unsigned int mod, unsigned int k) { modifiers = mod; key = k; }
-} Binding;
-
-typedef struct KeyBindingTree {
- Binding binding;
- KeyCallbackList callbacks; // the callbacks given for the binding in add()
- bool chain; // true if this is a chain to another key (not an action)
-
- struct KeyBindingTree *next_sibling; // the next binding in the tree at the same
- // level
- struct KeyBindingTree *first_child; // the first child of this binding (next
- // binding in a chained sequence).
- KeyBindingTree() : binding(0, 0) {
- chain = true; next_sibling = first_child = 0;
- }
-} KeyBindingTree;
-
-typedef struct ButtonBinding {
- Binding binding;
- MouseCallbackList callbacks[MouseAction::NUM_MOUSE_ACTION];
- ButtonBinding() : binding(0, 0) {}
-};
-
-class Bindings {
-public:
- //! A list of strings
- typedef std::vector<std::string> StringVect;
-
-private:
- // root node of the tree (this doesn't have siblings!)
- KeyBindingTree _keytree;
- KeyBindingTree *_curpos; // position in the keytree
-
- Binding _resetkey; // the key which resets the key chain status
-
- otk::Timer *_timer;
-
- KeyBindingTree *find(KeyBindingTree *search, bool *conflict) const;
- KeyBindingTree *buildtree(const StringVect &keylist,
- KeyCallback callback, void *data) const;
- void assimilate(KeyBindingTree *node);
-
- static void resetChains(Bindings *self); // the timer's timeout function
-
- typedef std::list <ButtonBinding*> ButtonBindingList;
- ButtonBindingList _buttons[MouseContext::NUM_MOUSE_CONTEXT];
-
- void grabButton(bool grab, const Binding &b, MouseContext::MC context,
- Client *client);
-
- EventCallbackList _eventlist[EventAction::NUM_EVENT_ACTION];
-
- KeyCallbackData _keybgrab_callback;
-
- bool _grabbed;
-
-public:
- //! Initializes an Bindings object
- Bindings();
- //! Destroys the Bindings object
- virtual ~Bindings();
-
- //! Translates a binding string into the actual Binding
- bool translate(const std::string &str, Binding &b, bool askey = true) const;
-
- //! Adds a new key binding
- /*!
- A binding will fail to be added if the binding already exists (as part of
- a chain or not), or if any of the strings in the keylist are invalid.
- @return true if the binding could be added; false if it could not.
- */
- bool addKey(const StringVect &keylist, KeyCallback callback, void *data);
-
- ////! Removes a key binding
- ///*!
- // @return The callbackid of the binding, or '< 0' if there was no binding to
- // be removed.
- //*/
- //bool removeKey(const StringVect &keylist, KeyCallback callback, void *data);
-
- //! Removes all key bindings
- void removeAllKeys();
-
- void fireKey(int screen, unsigned int modifiers,unsigned int key, Time time,
- KeyAction::KA action);
-
- void setResetKey(const std::string &key);
-
- void grabKeys(bool grab);
-
- bool grabKeyboard(int screen, KeyCallback callback, void *data);
- void ungrabKeyboard();
-
- bool grabPointer(int screen);
- void ungrabPointer();
-
- bool addButton(const std::string &but, MouseContext::MC context,
- MouseAction::MA action, MouseCallback callback, void *data);
-
- void grabButtons(bool grab, Client *client);
-
- //! Removes all button bindings
- void removeAllButtons();
-
- void fireButton(MouseData *data);
-
- //! Bind a callback for an event
- bool addEvent(EventAction::EA action, EventCallback callback, void *data);
-
- //! Unbind the callback function from an event
- bool removeEvent(EventAction::EA action, EventCallback callback, void *data);
-
- //! Remove all callback functions
- void removeAllEvents();
-
- void fireEvent(EventData *data);
-};
-
-}
-
-#endif // __binding_hh
diff --git a/src/client.cc b/src/client.cc
deleted file mode 100644
index 2e78cb76..00000000
--- a/src/client.cc
+++ /dev/null
@@ -1,2014 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#include "config.h"
-
-#include "client.hh"
-#include "frame.hh"
-#include "screen.hh"
-#include "openbox.hh"
-#include "bindings.hh"
-#include "otk/display.hh"
-#include "otk/property.hh"
-
-extern "C" {
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-
-#include "gettext.h"
-#define _(str) gettext(str)
-}
-
-#include <cstring> // for memcpy
-#include <climits>
-#include <cassert>
-#include <algorithm>
-
-namespace ob {
-
-Client::Client(int screen, Window window)
- : otk::EventHandler(),
- frame(0), _screen(screen), _window(window)
-{
- assert(screen >= 0);
- assert(window);
-
- ignore_unmaps = 0;
-
- // update EVERYTHING the first time!!
-
- // defaults
- _wmstate = NormalState;
- _focused = false;
- _transient_for = 0;
- _layer = Layer_Normal;
- _urgent = false;
- _positioned = false;
- _disabled_decorations = 0;
- _group = None;
- _desktop = 0;
- _nicons = 0;
-
- getArea();
- getDesktop();
- getState(); // do this before updateTransientFor! (for _modal)
- getShaped();
-
- updateTransientFor();
- getMwmHints();
- getType(); // this can change the mwmhints for special cases
-
- updateProtocols();
-
- getGravity(); // get the attribute gravity
- updateNormalHints(); // this may override the attribute gravity
-
- // got the type, the mwmhints, the protocols, and the normal hints (min/max
- // sizes), so we're ready to set up
- // the decorations/functions
- setupDecorAndFunctions();
-
- // also get the initial_state and set _iconic if we aren't "starting"
- // when we're "starting" that means we should use whatever state was already
- // on the window over the initial map state, because it was already mapped
- updateWMHints(openbox->state() != Openbox::State_Starting);
- updateTitle();
- updateIconTitle();
- updateClass();
- updateStrut();
- updateIcons();
- updateKwmIcon();
-
- // this makes sure that these windows appear on all desktops
- if (/*_type == Type_Dock ||*/ _type == Type_Desktop)
- _desktop = 0xffffffff;
-
- // set the desktop hint, to make sure that it always exists, and to reflect
- // any changes we've made here
- otk::Property::set(_window, otk::Property::atoms.net_wm_desktop,
- otk::Property::atoms.cardinal, (unsigned)_desktop);
- changeState();
-}
-
-
-Client::~Client()
-{
- assert(_nicons > 0); // there should always be a default..
- for (int j = 0; j < _nicons; ++j)
- delete [] _icons[j].data;
- delete [] _icons;
-
- // clean up childrens' references
- while (!_transients.empty()) {
- _transients.front()->_transient_for = 0;
- _transients.pop_front();
- }
-
- // clean up parents reference to this
- if (_transient_for)
- _transient_for->_transients.remove(this); // remove from old parent
-
- if (openbox->state() != Openbox::State_Exiting) {
- // these values should not be persisted across a window unmapping/mapping
- otk::Property::erase(_window, otk::Property::atoms.net_wm_desktop);
- otk::Property::erase(_window, otk::Property::atoms.net_wm_state);
- } else {
- // if we're left in an iconic state, the client wont be mapped. this is
- // bad, since we will no longer be managing the window on restart
- if (_iconic)
- XMapWindow(**otk::display, _window);
- }
-}
-
-
-bool Client::validate() const
-{
- XSync(**otk::display, false); // get all events on the server
-
- XEvent e;
- if (XCheckTypedWindowEvent(**otk::display, _window, DestroyNotify, &e) ||
- XCheckTypedWindowEvent(**otk::display, _window, UnmapNotify, &e)) {
- XPutBackEvent(**otk::display, &e);
- return false;
- }
-
- return true;
-}
-
-
-void Client::getGravity()
-{
- XWindowAttributes wattrib;
- Status ret;
-
- ret = XGetWindowAttributes(**otk::display, _window, &wattrib);
- assert(ret != BadWindow);
- _gravity = wattrib.win_gravity;
-}
-
-
-void Client::getDesktop()
-{
- // defaults to the current desktop
- _desktop = openbox->screen(_screen)->desktop();
- unsigned int d;
-
- if (otk::Property::get(_window, otk::Property::atoms.net_wm_desktop,
- otk::Property::atoms.cardinal,
- (long unsigned*)&d)) {
- if (d >= openbox->screen(_screen)->numDesktops() &&
- d != 0xffffffff)
- d = openbox->screen(_screen)->numDesktops() - 1;
- _desktop = d;
-#ifdef DEBUG
-// printf("Window requested desktop: %ld\n", _desktop);
-#endif
- }
-}
-
-
-void Client::getType()
-{
- _type = (WindowType) -1;
-
- unsigned long *val;
- unsigned long num;
- if (otk::Property::get(_window, otk::Property::atoms.net_wm_window_type,
- otk::Property::atoms.atom, &num, &val)) {
- // use the first value that we know about in the array
- for (unsigned long i = 0; i < num; ++i) {
- if (val[i] == otk::Property::atoms.net_wm_window_type_desktop)
- _type = Type_Desktop;
- else if (val[i] == otk::Property::atoms.net_wm_window_type_dock)
- _type = Type_Dock;
- else if (val[i] == otk::Property::atoms.net_wm_window_type_toolbar)
- _type = Type_Toolbar;
- else if (val[i] == otk::Property::atoms.net_wm_window_type_menu)
- _type = Type_Menu;
- else if (val[i] == otk::Property::atoms.net_wm_window_type_utility)
- _type = Type_Utility;
- else if (val[i] == otk::Property::atoms.net_wm_window_type_splash)
- _type = Type_Splash;
- else if (val[i] == otk::Property::atoms.net_wm_window_type_dialog)
- _type = Type_Dialog;
- else if (val[i] == otk::Property::atoms.net_wm_window_type_normal)
- _type = Type_Normal;
- else if (val[i] == otk::Property::atoms.kde_net_wm_window_type_override){
- // prevent this window from getting any decor or functionality
- _mwmhints.flags &= MwmFlag_Functions | MwmFlag_Decorations;
- _mwmhints.decorations = 0;
- _mwmhints.functions = 0;
- }
- if (_type != (WindowType) -1)
- break; // grab the first known type
- }
- delete val;
- }
-
- if (_type == (WindowType) -1) {
- /*
- * the window type hint was not set, which means we either classify ourself
- * as a normal window or a dialog, depending on if we are a transient.
- */
- if (_transient_for)
- _type = Type_Dialog;
- else
- _type = Type_Normal;
- }
-}
-
-
-void Client::setupDecorAndFunctions()
-{
- // start with everything (cept fullscreen)
- _decorations = Decor_Titlebar | Decor_Handle | Decor_Border | Decor_Icon |
- Decor_AllDesktops | Decor_Iconify | Decor_Maximize;
- _functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize |
- Func_Shade;
- if (_delete_window) {
- _decorations |= Decor_Close;
- _functions |= Func_Close;
- }
-
- if (!(_min_size.width() < _max_size.width() ||
- _min_size.height() < _max_size.height())) {
- _decorations &= ~(Decor_Maximize | Decor_Handle);
- _functions &= ~(Func_Resize | Func_Maximize);
- }
-
- switch (_type) {
- case Type_Normal:
- // normal windows retain all of the possible decorations and
- // functionality, and are the only windows that you can fullscreen
- _functions |= Func_Fullscreen;
- break;
-
- case Type_Dialog:
- // dialogs cannot be maximized
- _decorations &= ~Decor_Maximize;
- _functions &= ~Func_Maximize;
- break;
-
- case Type_Menu:
- case Type_Toolbar:
- case Type_Utility:
- // these windows get less functionality
- _decorations &= ~(Decor_Iconify | Decor_Handle);
- _functions &= ~(Func_Iconify | Func_Resize);
- break;
-
- case Type_Desktop:
- case Type_Dock:
- case Type_Splash:
- // none of these windows are manipulated by the window manager
- _decorations = 0;
- _functions = 0;
- break;
- }
-
- // Mwm Hints are applied subtractively to what has already been chosen for
- // decor and functionality
- if (_mwmhints.flags & MwmFlag_Decorations) {
- if (! (_mwmhints.decorations & MwmDecor_All)) {
- if (! (_mwmhints.decorations & MwmDecor_Border))
- _decorations &= ~Decor_Border;
- if (! (_mwmhints.decorations & MwmDecor_Handle))
- _decorations &= ~Decor_Handle;
- if (! (_mwmhints.decorations & MwmDecor_Title))
- _decorations &= ~Decor_Titlebar;
- if (! (_mwmhints.decorations & MwmDecor_Iconify))
- _decorations &= ~Decor_Iconify;
- if (! (_mwmhints.decorations & MwmDecor_Maximize))
- _decorations &= ~Decor_Maximize;
- }
- }
-
- if (_mwmhints.flags & MwmFlag_Functions) {
- if (! (_mwmhints.functions & MwmFunc_All)) {
- if (! (_mwmhints.functions & MwmFunc_Resize))
- _functions &= ~Func_Resize;
- if (! (_mwmhints.functions & MwmFunc_Move))
- _functions &= ~Func_Move;
- if (! (_mwmhints.functions & MwmFunc_Iconify))
- _functions &= ~Func_Iconify;
- if (! (_mwmhints.functions & MwmFunc_Maximize))
- _functions &= ~Func_Maximize;
- // dont let mwm hints kill the close button
- //if (! (_mwmhints.functions & MwmFunc_Close))
- // _functions &= ~Func_Close;
- }
- }
-
- // can't maximize without moving/resizing
- if (!((_functions & Func_Move) && (_functions & Func_Resize)))
- _functions &= ~Func_Maximize;
-
- // finally, user specified disabled decorations are applied to subtract
- // decorations
- if (_disabled_decorations & Decor_Titlebar)
- _decorations &= ~Decor_Titlebar;
- if (_disabled_decorations & Decor_Handle)
- _decorations &= ~Decor_Handle;
- if (_disabled_decorations & Decor_Border)
- _decorations &= ~Decor_Border;
- if (_disabled_decorations & Decor_Iconify)
- _decorations &= ~Decor_Iconify;
- if (_disabled_decorations & Decor_Maximize)
- _decorations &= ~Decor_Maximize;
- if (_disabled_decorations & Decor_AllDesktops)
- _decorations &= ~Decor_AllDesktops;
- if (_disabled_decorations & Decor_Close)
- _decorations &= ~Decor_Close;
-
- // if we don't have a titlebar, then we cannot shade!
- if (!(_decorations & Decor_Titlebar))
- _functions &= ~Func_Shade;
-
- changeAllowedActions();
-
- if (frame) {
- frame->adjustSize(); // change the decors on the frame
- frame->adjustPosition(); // with more/less decorations, we may need to be
- // moved
- remaximize(); // with new decor, the window's maximized size may change
- }
-}
-
-
-void Client::getMwmHints()
-{
- unsigned long num = MwmHints::elements;
- unsigned long *hints;
-
- _mwmhints.flags = 0; // default to none
-
- if (!otk::Property::get(_window, otk::Property::atoms.motif_wm_hints,
- otk::Property::atoms.motif_wm_hints, &num,
- (unsigned long **)&hints))
- return;
-
- if (num >= MwmHints::elements) {
- // retrieved the hints
- _mwmhints.flags = hints[0];
- _mwmhints.functions = hints[1];
- _mwmhints.decorations = hints[2];
- }
-
- delete [] hints;
-}
-
-
-void Client::getArea()
-{
- XWindowAttributes wattrib;
- Status ret;
-
- ret = XGetWindowAttributes(**otk::display, _window, &wattrib);
- assert(ret != BadWindow);
-
- _area = otk::Rect(wattrib.x, wattrib.y, wattrib.width, wattrib.height);
- _border_width = wattrib.border_width;
-}
-
-
-void Client::getState()
-{
- _modal = _shaded = _max_horz = _max_vert = _fullscreen = _above = _below =
- _iconic = _skip_taskbar = _skip_pager = false;
-
- unsigned long *state;
- unsigned long num;
-
- if (otk::Property::get(_window, otk::Property::atoms.net_wm_state,
- otk::Property::atoms.atom, &num, &state)) {
- for (unsigned long i = 0; i < num; ++i) {
- if (state[i] == otk::Property::atoms.net_wm_state_modal)
- _modal = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_shaded)
- _shaded = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_hidden)
- _iconic = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_skip_taskbar)
- _skip_taskbar = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_skip_pager)
- _skip_pager = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_fullscreen)
- _fullscreen = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_maximized_vert)
- _max_vert = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_maximized_horz)
- _max_horz = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_above)
- _above = true;
- else if (state[i] == otk::Property::atoms.net_wm_state_below)
- _below = true;
- }
-
- delete [] state;
- }
-}
-
-void Client::getShaped()
-{
- _shaped = false;
-#ifdef SHAPE
- if (otk::display->shape()) {
- int foo;
- unsigned int ufoo;
- int s;
-
- XShapeSelectInput(**otk::display, _window, ShapeNotifyMask);
-
- XShapeQueryExtents(**otk::display, _window, &s, &foo,
- &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo);
- _shaped = (s != 0);
- }
-#endif // SHAPE
-}
-
-Client *Client::searchFocusTree(Client *node, Client *skip)
-{
- List::const_iterator it, end = node->_transients.end();
- Client *ret;
-
- for (it = node->_transients.begin(); it != end; ++it) {
- if (*it == skip) continue; // circular?
- if ((ret = searchModalTree(*it, skip))) return ret; // got one
- if ((*it)->_focused) return *it; // got one
- }
- return 0;
-}
-
-void Client::calcLayer() {
- StackLayer l;
- bool fs = false;
-
- // are we fullscreen, or do we have a fullscreen transient parent?
- Client *c = this;
- while (c) {
- if (c->_fullscreen) {
- fs =true;
- break;
- }
- c = c->_transient_for;
- }
- if (!fs && _fullscreen) {
- // is one of our transients focused?
- c = searchFocusTree(this, this);
- if (c) fs = true;
- }
-
- if (_iconic) l = Layer_Icon;
- else if (fs) l = Layer_Fullscreen;
- else if (_type == Type_Desktop) l = Layer_Desktop;
- else if (_type == Type_Dock) {
- if (!_below) l = Layer_Top;
- else l = Layer_Normal;
- }
- else if (_above) l = Layer_Above;
- else if (_below) l = Layer_Below;
- else l = Layer_Normal;
-
- if (l != _layer) {
- _layer = l;
- if (frame) {
- /*
- if we don't have a frame, then we aren't mapped yet (and this would
- SIGSEGV :)
- */
- openbox->screen(_screen)->raiseWindow(this);
- }
- }
-}
-
-void Client::updateProtocols()
-{
- Atom *proto;
- int num_return = 0;
-
- _focus_notify = false;
- _delete_window = false;
-
- if (XGetWMProtocols(**otk::display, _window, &proto, &num_return)) {
- for (int i = 0; i < num_return; ++i) {
- if (proto[i] == otk::Property::atoms.wm_delete_window) {
- // this means we can request the window to close
- _delete_window = true;
- } else if (proto[i] == otk::Property::atoms.wm_take_focus)
- // if this protocol is requested, then the window will be notified
- // by the window manager whenever it receives focus
- _focus_notify = true;
- }
- XFree(proto);
- }
-}
-
-void Client::updateNormalHints()
-{
- XSizeHints size;
- long ret;
- int oldgravity = _gravity;
-
- // defaults
- _min_ratio = 0.0;
- _max_ratio = 0.0;
- _size_inc = otk::Size(1, 1);
- _base_size = otk::Size(0, 0);
- _min_size = otk::Size(0, 0);
- _max_size = otk::Size(INT_MAX, INT_MAX);
-
- // get the hints from the window
- if (XGetWMNormalHints(**otk::display, _window, &size, &ret)) {
- _positioned = (size.flags & (PPosition|USPosition));
-
- if (size.flags & PWinGravity) {
- _gravity = size.win_gravity;
-
- // if the client has a frame, i.e. has already been mapped and is
- // changing its gravity
- if (frame && _gravity != oldgravity) {
- // move our idea of the client's position based on its new gravity
- int x = frame->area().x(), y = frame->area().y();
- frame->frameGravity(x, y);
- _area = otk::Rect(otk::Point(x, y), _area.size());
- }
- }
-
- if (size.flags & PAspect) {
- if (size.min_aspect.y) _min_ratio = size.min_aspect.x/size.min_aspect.y;
- if (size.max_aspect.y) _max_ratio = size.max_aspect.x/size.max_aspect.y;
- }
-
- if (size.flags & PMinSize)
- _min_size = otk::Size(size.min_width, size.min_height);
-
- if (size.flags & PMaxSize)
- _max_size = otk::Size(size.max_width, size.max_height);
-
- if (size.flags & PBaseSize)
- _base_size = otk::Size(size.base_width, size.base_height);
-
- if (size.flags & PResizeInc)
- _size_inc = otk::Size(size.width_inc, size.height_inc);
- }
-}
-
-void Client::updateWMHints(bool initstate)
-{
- XWMHints *hints;
-
- // assume a window takes input if it doesnt specify
- _can_focus = true;
- bool ur = false;
-
- if ((hints = XGetWMHints(**otk::display, _window)) != NULL) {
- if (hints->flags & InputHint)
- _can_focus = hints->input;
-
- // only do this when initstate is true!
- if (initstate && (hints->flags & StateHint))
- _iconic = hints->initial_state == IconicState;
-
- if (hints->flags & XUrgencyHint)
- ur = true;
-
- if (hints->flags & WindowGroupHint) {
- if (hints->window_group != _group) {
- // XXX: remove from the old group if there was one
- _group = hints->window_group;
- // XXX: do stuff with the group
- }
- } else // no group!
- _group = None;
-
- if (hints->flags & IconPixmapHint) {
- updateKwmIcon(); // try get the kwm icon first, this is a fallback only
- if (_pixmap_icon == None) {
- _pixmap_icon = hints->icon_pixmap;
- if (hints->flags & IconMaskHint)
- _pixmap_icon_mask = hints->icon_mask;
- else
- _pixmap_icon_mask = None;
- }
- }
-
- XFree(hints);
- }
-
- if (ur != _urgent) {
- _urgent = ur;
-#ifdef DEBUG
- printf("Urgent Hint for 0x%lx: %s\n",
- (long)_window, _urgent ? "ON" : "OFF");
-#endif
- // fire the urgent callback if we're mapped, otherwise, wait until after
- // we're mapped
- if (frame)
- fireUrgent();
- }
-}
-
-void Client::updateTitle()
-{
- _title = "";
-
- // try netwm
- if (!otk::Property::get(_window, otk::Property::atoms.net_wm_name,
- otk::Property::utf8, &_title)) {
- // try old x stuff
- otk::Property::get(_window, otk::Property::atoms.wm_name,
- otk::Property::ascii, &_title);
- }
-
- if (_title.empty())
- _title = _("Unnamed Window");
-
- if (frame)
- frame->adjustTitle();
-}
-
-void Client::updateIconTitle()
-{
- _icon_title = "";
-
- // try netwm
- if (!otk::Property::get(_window, otk::Property::atoms.net_wm_icon_name,
- otk::Property::utf8, &_icon_title)) {
- // try old x stuff
- otk::Property::get(_window, otk::Property::atoms.wm_icon_name,
- otk::Property::ascii, &_icon_title);
- }
-
- if (_title.empty())
- _icon_title = _("Unnamed Window");
-}
-
-void Client::updateClass()
-{
- // set the defaults
- _app_name = _app_class = _role = "";
-
- otk::Property::StringVect v;
- unsigned long num = 2;
-
- if (otk::Property::get(_window, otk::Property::atoms.wm_class,
- otk::Property::ascii, &num, &v)) {
- if (num > 0) _app_name = v[0].c_str();
- if (num > 1) _app_class = v[1].c_str();
- }
-
- v.clear();
- num = 1;
- if (otk::Property::get(_window, otk::Property::atoms.wm_window_role,
- otk::Property::ascii, &num, &v)) {
- if (num > 0) _role = v[0].c_str();
- }
-}
-
-void Client::updateStrut()
-{
- unsigned long num = 4;
- unsigned long *data;
- if (!otk::Property::get(_window, otk::Property::atoms.net_wm_strut,
- otk::Property::atoms.cardinal, &num, &data))
- return;
-
- if (num == 4) {
- _strut.left = data[0];
- _strut.right = data[1];
- _strut.top = data[2];
- _strut.bottom = data[3];
-
- // updating here is pointless while we're being mapped cuz we're not in
- // the screen's client list yet
- if (frame)
- openbox->screen(_screen)->updateStruts();
- }
-
- delete [] data;
-}
-
-void Client::updateTransientFor()
-{
- Window t = 0;
- Client *c = 0;
-
- if (XGetTransientForHint(**otk::display, _window, &t) &&
- t != _window) { // cant be transient to itself!
- c = openbox->findClient(t);
- assert(c != this); // if this happens then we need to check for it
-
- if (!c /*XXX: && _group*/) {
- // not transient to a client, see if it is transient for a group
- if (//t == _group->leader() ||
- t == None ||
- t == otk::display->screenInfo(_screen)->rootWindow()) {
- // window is a transient for its group!
- // XXX: for now this is treated as non-transient.
- // this needs to be fixed!
- }
- }
- }
-
- // if anything has changed...
- if (c != _transient_for) {
- if (_transient_for)
- _transient_for->_transients.remove(this); // remove from old parent
- _transient_for = c;
- if (_transient_for)
- _transient_for->_transients.push_back(this); // add to new parent
- }
-}
-
-void Client::updateIcons()
-{
- unsigned long num;
- unsigned long *data;
- unsigned long w, h, i = 0;
-
- for (int j = 0; j < _nicons; ++j)
- delete [] _icons[j].data;
- if (_nicons > 0)
- delete [] _icons;
- _nicons = 0;
-
- if (otk::Property::get(_window, otk::Property::atoms.net_wm_icon,
- otk::Property::atoms.cardinal, &num, &data)) {
- // figure out how man valid icons are in here
- while (num - i > 2) {
- w = data[i++];
- h = data[i++];
- i += w * h;
- if (i > num) break;
- ++_nicons;
- }
-
- _icons = new Icon[_nicons];
-
- // store the icons
- i = 0;
- for (int j = 0; j < _nicons; ++j) {
- w = _icons[j].w = data[i++];
- h = _icons[j].h = data[i++];
- _icons[j].data = new unsigned long[w * h];
- ::memcpy(_icons[j].data, &data[i], w * h * sizeof(unsigned long));
- i += w * h;
- assert(i <= num);
- }
-
- delete [] data;
- }
-
- if (_nicons <= 0) {
- _nicons = 1;
- _icons = new Icon[1];
- _icons[i].w = 0;
- _icons[i].h = 0;
- _icons[i].data = 0;
- }
-
- assert(_nicons > 0); // there should always be a default..
-
- if (frame) frame->adjustIcon();
-}
-
-void Client::updateKwmIcon()
-{
- _pixmap_icon = _pixmap_icon_mask = None;
-
- unsigned long num = 2;
- Pixmap *data;
- if (otk::Property::get(_window, otk::Property::atoms.kwm_win_icon,
- otk::Property::atoms.kwm_win_icon, &num, &data)) {
- if (num == 2) {
- _pixmap_icon = data[0];
- _pixmap_icon_mask = data[1];
- }
- delete [] data;
- }
-}
-
-void Client::propertyHandler(const XPropertyEvent &e)
-{
- otk::EventHandler::propertyHandler(e);
-
- // validate cuz we query stuff off the client here
- if (!validate()) return;
-
- // compress changes to a single property into a single change
- XEvent ce;
- while (XCheckTypedEvent(**otk::display, e.type, &ce)) {
- // XXX: it would be nice to compress ALL changes to a property, not just
- // changes in a row without other props between.
- if (ce.xproperty.atom != e.atom) {
- XPutBackEvent(**otk::display, &ce);
- break;
- }
- }
-
- if (e.atom == XA_WM_NORMAL_HINTS) {
- updateNormalHints();
- setupDecorAndFunctions(); // normal hints can make a window non-resizable
- } else if (e.atom == XA_WM_HINTS)
- updateWMHints();
- else if (e.atom == XA_WM_TRANSIENT_FOR) {
- updateTransientFor();
- getType();
- calcLayer(); // type may have changed, so update the layer
- setupDecorAndFunctions();
- }
- else if (e.atom == otk::Property::atoms.net_wm_name ||
- e.atom == otk::Property::atoms.wm_name)
- updateTitle();
- else if (e.atom == otk::Property::atoms.net_wm_icon_name ||
- e.atom == otk::Property::atoms.wm_icon_name)
- updateIconTitle();
- else if (e.atom == otk::Property::atoms.wm_class)
- updateClass();
- else if (e.atom == otk::Property::atoms.wm_protocols) {
- updateProtocols();
- setupDecorAndFunctions();
- }
- else if (e.atom == otk::Property::atoms.net_wm_strut)
- updateStrut();
- else if (e.atom == otk::Property::atoms.net_wm_icon)
- updateIcons();
- else if (e.atom == otk::Property::atoms.kwm_win_icon)
- updateKwmIcon();
-}
-
-void Client::setWMState(long state)
-{
- if (state == _wmstate) return; // no change
-
- switch (state) {
- case IconicState:
- iconify(true);
- break;
- case NormalState:
- iconify(false);
- break;
- }
-}
-
-void Client::setDesktop(unsigned int target)
-{
- if (target == _desktop) return;
-
- printf("Setting desktop %u\n", target);
-
- if (!(target < openbox->screen(_screen)->numDesktops() ||
- target == 0xffffffff))
- return;
-
- _desktop = target;
- // set the desktop hint
- otk::Property::set(_window, otk::Property::atoms.net_wm_desktop,
- otk::Property::atoms.cardinal, _desktop);
- frame->adjustState(); // the frame can display the current desktop state
- // 'move' the window to the new desktop
- showhide();
- openbox->screen(_screen)->updateStruts();
-}
-
-void Client::showhide()
-{
- bool show;
- Screen *s = openbox->screen(_screen);
-
- if (_iconic) show = false;
- else if (!(_desktop == s->desktop() ||
- _desktop == 0xffffffff)) show = false;
- else if (normal() && s->showingDesktop()) show = false;
- else show = true;
-
- if (show) frame->show();
- else frame->hide();
-}
-
-void Client::setState(Atom action, long data1, long data2)
-{
- bool shadestate = _shaded;
- bool fsstate = _fullscreen;
- bool maxh = _max_horz;
- bool maxv = _max_vert;
-
- if (!(action == otk::Property::atoms.net_wm_state_add ||
- action == otk::Property::atoms.net_wm_state_remove ||
- action == otk::Property::atoms.net_wm_state_toggle))
- return; // an invalid action was passed to the client message, ignore it
-
- for (int i = 0; i < 2; ++i) {
- Atom state = i == 0 ? data1 : data2;
-
- if (! state) continue;
-
- // if toggling, then pick whether we're adding or removing
- if (action == otk::Property::atoms.net_wm_state_toggle) {
- if (state == otk::Property::atoms.net_wm_state_modal)
- action = _modal ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- else if (state == otk::Property::atoms.net_wm_state_maximized_vert)
- action = _max_vert ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- else if (state == otk::Property::atoms.net_wm_state_maximized_horz)
- action = _max_horz ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- else if (state == otk::Property::atoms.net_wm_state_shaded)
- action = _shaded ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- else if (state == otk::Property::atoms.net_wm_state_skip_taskbar)
- action = _skip_taskbar ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- else if (state == otk::Property::atoms.net_wm_state_skip_pager)
- action = _skip_pager ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- else if (state == otk::Property::atoms.net_wm_state_fullscreen)
- action = _fullscreen ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- else if (state == otk::Property::atoms.net_wm_state_above)
- action = _above ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- else if (state == otk::Property::atoms.net_wm_state_below)
- action = _below ? otk::Property::atoms.net_wm_state_remove :
- otk::Property::atoms.net_wm_state_add;
- }
-
- if (action == otk::Property::atoms.net_wm_state_add) {
- if (state == otk::Property::atoms.net_wm_state_modal) {
- if (_modal) continue;
- _modal = true;
- } else if (state == otk::Property::atoms.net_wm_state_maximized_vert) {
- maxv = true;
- } else if (state == otk::Property::atoms.net_wm_state_maximized_horz) {
- if (_max_horz) continue;
- maxh = true;
- } else if (state == otk::Property::atoms.net_wm_state_shaded) {
- shadestate = true;
- } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) {
- _skip_taskbar = true;
- } else if (state == otk::Property::atoms.net_wm_state_skip_pager) {
- _skip_pager = true;
- } else if (state == otk::Property::atoms.net_wm_state_fullscreen) {
- fsstate = true;
- } else if (state == otk::Property::atoms.net_wm_state_above) {
- if (_above) continue;
- _above = true;
- } else if (state == otk::Property::atoms.net_wm_state_below) {
- if (_below) continue;
- _below = true;
- }
-
- } else { // action == otk::Property::atoms.net_wm_state_remove
- if (state == otk::Property::atoms.net_wm_state_modal) {
- if (!_modal) continue;
- _modal = false;
- } else if (state == otk::Property::atoms.net_wm_state_maximized_vert) {
- maxv = false;
- } else if (state == otk::Property::atoms.net_wm_state_maximized_horz) {
- maxh = false;
- } else if (state == otk::Property::atoms.net_wm_state_shaded) {
- shadestate = false;
- } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) {
- _skip_taskbar = false;
- } else if (state == otk::Property::atoms.net_wm_state_skip_pager) {
- _skip_pager = false;
- } else if (state == otk::Property::atoms.net_wm_state_fullscreen) {
- fsstate = false;
- } else if (state == otk::Property::atoms.net_wm_state_above) {
- if (!_above) continue;
- _above = false;
- } else if (state == otk::Property::atoms.net_wm_state_below) {
- if (!_below) continue;
- _below = false;
- }
- }
- }
- if (maxh != _max_horz || maxv != _max_vert) {
- if (maxh != _max_horz && maxv != _max_vert) { // toggling both
- if (maxh == maxv) { // both going the same way
- maximize(maxh, 0, true);
- } else {
- maximize(maxh, 1, true);
- maximize(maxv, 2, true);
- }
- } else { // toggling one
- if (maxh != _max_horz)
- maximize(maxh, 1, true);
- else
- maximize(maxv, 2, true);
- }
- }
- // change fullscreen state before shading, as it will affect if the window
- // can shade or not
- if (fsstate != _fullscreen)
- fullscreen(fsstate, true);
- if (shadestate != _shaded)
- shade(shadestate);
- calcLayer();
- changeState(); // change the hint to relect these changes
-}
-
-void Client::toggleClientBorder(bool addborder)
-{
- // adjust our idea of where the client is, based on its border. When the
- // border is removed, the client should now be considered to be in a
- // different position.
- // when re-adding the border to the client, the same operation needs to be
- // reversed.
- int oldx = _area.x(), oldy = _area.y();
- int x = oldx, y = oldy;
- switch(_gravity) {
- default:
- case NorthWestGravity:
- case WestGravity:
- case SouthWestGravity:
- break;
- case NorthEastGravity:
- case EastGravity:
- case SouthEastGravity:
- if (addborder) x -= _border_width * 2;
- else x += _border_width * 2;
- break;
- case NorthGravity:
- case SouthGravity:
- case CenterGravity:
- case ForgetGravity:
- case StaticGravity:
- if (addborder) x -= _border_width;
- else x += _border_width;
- break;
- }
- switch(_gravity) {
- default:
- case NorthWestGravity:
- case NorthGravity:
- case NorthEastGravity:
- break;
- case SouthWestGravity:
- case SouthGravity:
- case SouthEastGravity:
- if (addborder) y -= _border_width * 2;
- else y += _border_width * 2;
- break;
- case WestGravity:
- case EastGravity:
- case CenterGravity:
- case ForgetGravity:
- case StaticGravity:
- if (addborder) y -= _border_width;
- else y += _border_width;
- break;
- }
- _area = otk::Rect(otk::Point(x, y), _area.size());
-
- if (addborder) {
- XSetWindowBorderWidth(**otk::display, _window, _border_width);
-
- // move the client so it is back it the right spot _with_ its border!
- if (x != oldx || y != oldy)
- XMoveWindow(**otk::display, _window, x, y);
- } else
- XSetWindowBorderWidth(**otk::display, _window, 0);
-}
-
-void Client::clientMessageHandler(const XClientMessageEvent &e)
-{
- otk::EventHandler::clientMessageHandler(e);
-
- // validate cuz we query stuff off the client here
- if (!validate()) return;
-
- if (e.format != 32) return;
-
- if (e.message_type == otk::Property::atoms.wm_change_state) {
- // compress changes into a single change
- bool compress = false;
- XEvent ce;
- while (XCheckTypedEvent(**otk::display, e.type, &ce)) {
- // XXX: it would be nice to compress ALL messages of a type, not just
- // messages in a row without other message types between.
- if (ce.xclient.message_type != e.message_type) {
- XPutBackEvent(**otk::display, &ce);
- break;
- }
- compress = true;
- }
- if (compress)
- setWMState(ce.xclient.data.l[0]); // use the found event
- else
- setWMState(e.data.l[0]); // use the original event
- } else if (e.message_type == otk::Property::atoms.net_wm_desktop) {
- // compress changes into a single change
- bool compress = false;
- XEvent ce;
- while (XCheckTypedEvent(**otk::display, e.type, &ce)) {
- // XXX: it would be nice to compress ALL messages of a type, not just
- // messages in a row without other message types between.
- if (ce.xclient.message_type != e.message_type) {
- XPutBackEvent(**otk::display, &ce);
- break;
- }
- compress = true;
- }
- if (compress)
- setDesktop(e.data.l[0]); // use the found event
- else
- setDesktop(e.data.l[0]); // use the original event
- } else if (e.message_type == otk::Property::atoms.net_wm_state) {
- // can't compress these
-#ifdef DEBUG
- printf("net_wm_state %s %ld %ld for 0x%lx\n",
- (e.data.l[0] == 0 ? "Remove" : e.data.l[0] == 1 ? "Add" :
- e.data.l[0] == 2 ? "Toggle" : "INVALID"),
- e.data.l[1], e.data.l[2], _window);
-#endif
- setState(e.data.l[0], e.data.l[1], e.data.l[2]);
- } else if (e.message_type == otk::Property::atoms.net_close_window) {
-#ifdef DEBUG
- printf("net_close_window for 0x%lx\n", _window);
-#endif
- close();
- } else if (e.message_type == otk::Property::atoms.net_active_window) {
-#ifdef DEBUG
- printf("net_active_window for 0x%lx\n", _window);
-#endif
- if (openbox->screen(_screen)->showingDesktop())
- openbox->screen(_screen)->showDesktop(false);
- if (_iconic)
- iconify(false);
- else if (!frame->visible()) // if its not visible for other reasons, then
- return; // don't mess with it
- if (_shaded)
- shade(false);
- focus();
- openbox->screen(_screen)->raiseWindow(this);
- } else if (e.message_type == otk::Property::atoms.openbox_active_window) {
- if (openbox->screen(_screen)->showingDesktop())
- openbox->screen(_screen)->showDesktop(false);
- if (_iconic)
- iconify(false);
- else if (!frame->visible()) // if its not visible for other reasons, then
- return; // don't mess with it
- if (e.data.l[0] && _shaded)
- shade(false);
- focus();
- if (e.data.l[1])
- openbox->screen(_screen)->raiseWindow(this);
- } else if (e.message_type == otk::Property::atoms.openbox_restack_window) {
-#ifdef DEBUG
- printf("openbox_restack_window for 0x%lx\n", _window);
-#endif
- if (e.data.l[0] == 0)
- openbox->screen(_screen)->raiseWindow(this);
- else if (e.data.l[0] == 1)
- openbox->screen(_screen)->lowerWindow(this);
- }
-}
-
-#if defined(SHAPE)
-void Client::shapeHandler(const XShapeEvent &e)
-{
- otk::EventHandler::shapeHandler(e);
-
- if (e.kind == ShapeBounding) {
- _shaped = e.shaped;
- frame->adjustShape();
- }
-}
-#endif
-
-void Client::resize(Corner anchor, int w, int h)
-{
- if (!(_functions & Func_Resize)) return;
- internal_resize(anchor, w, h);
-}
-
-void Client::internal_resize(Corner anchor, int w, int h,
- bool user, int x, int y)
-{
- w -= _base_size.width();
- h -= _base_size.height();
-
- if (user) {
- // for interactive resizing. have to move half an increment in each
- // direction.
- int mw = w % _size_inc.width(); // how far we are towards the next size inc
- int mh = h % _size_inc.height();
- int aw = _size_inc.width() / 2; // amount to add
- int ah = _size_inc.height() / 2;
- // don't let us move into a new size increment
- if (mw + aw >= _size_inc.width()) aw = _size_inc.width() - mw - 1;
- if (mh + ah >= _size_inc.height()) ah = _size_inc.height() - mh - 1;
- w += aw;
- h += ah;
-
- // if this is a user-requested resize, then check against min/max sizes
- // and aspect ratios
-
- // smaller than min size or bigger than max size?
- if (w > _max_size.width()) w = _max_size.width();
- if (w < _min_size.width()) w = _min_size.width();
- if (h > _max_size.height()) h = _max_size.height();
- if (h < _min_size.height()) h = _min_size.height();
-
- // adjust the height ot match the width for the aspect ratios
- if (_min_ratio)
- if (h * _min_ratio > w) h = static_cast<int>(w / _min_ratio);
- if (_max_ratio)
- if (h * _max_ratio < w) h = static_cast<int>(w / _max_ratio);
- }
-
- // keep to the increments
- w /= _size_inc.width();
- h /= _size_inc.height();
-
- // you cannot resize to nothing
- if (w < 1) w = 1;
- if (h < 1) h = 1;
-
- // store the logical size
- _logical_size = otk::Size(w, h);
-
- w *= _size_inc.width();
- h *= _size_inc.height();
-
- w += _base_size.width();
- h += _base_size.height();
-
- if (x == INT_MIN || y == INT_MIN) {
- x = _area.x();
- y = _area.y();
- switch (anchor) {
- case TopLeft:
- break;
- case TopRight:
- x -= w - _area.width();
- break;
- case BottomLeft:
- y -= h - _area.height();
- break;
- case BottomRight:
- x -= w - _area.width();
- y -= h - _area.height();
- break;
- }
- }
-
- _area = otk::Rect(_area.position(), otk::Size(w, h));
-
- XResizeWindow(**otk::display, _window, w, h);
-
- // resize the frame to match the request
- frame->adjustSize();
- internal_move(x, y);
-}
-
-const Icon *Client::icon(const otk::Size &s) const
-{
- unsigned long req = s.width() * s.height();
- // si is the smallest image >= req
- // li is the largest image < req
- unsigned long smallest = 0xffffffff, largest = 0, si = 0, li = 0;
-
- assert(_nicons > 0); // there should always be a default..
- for (int i = 0; i < _nicons; ++i) {
- unsigned long size = _icons[i].w * _icons[i].h;
- if (size < smallest && size >= req) {
- smallest = size;
- si = i;
- }
- if (size > largest && size <= req) {
- largest = size;
- li = i;
- }
- }
- if (largest == 0) // didnt find one smaller than the requested size
- return &_icons[si];
- return &_icons[li];
-}
-
-void Client::move(int x, int y, bool final)
-{
- if (!(_functions & Func_Move)) return;
- frame->frameGravity(x, y); // get the client's position based on x,y for the
- // frame
- internal_move(x, y, final);
-}
-
-void Client::internal_move(int x, int y, bool final)
-{
- _area = otk::Rect(otk::Point(x, y), _area.size());
-
- // move the frame to be in the requested position
- if (frame) { // this can be called while mapping, before frame exists
- frame->adjustPosition();
-
- // send synthetic configure notify (we don't need to if we aren't mapped
- // yet)
- if (final) {
- XEvent event;
- event.type = ConfigureNotify;
- event.xconfigure.display = **otk::display;
- event.xconfigure.event = _window;
- event.xconfigure.window = _window;
-
- // root window coords with border in mind
- event.xconfigure.x = x - _border_width + frame->size().left;
- event.xconfigure.y = y - _border_width + frame->size().top;
-
- event.xconfigure.width = _area.width();
- event.xconfigure.height = _area.height();
- event.xconfigure.border_width = _border_width;
- event.xconfigure.above = frame->plate();
- event.xconfigure.override_redirect = False;
- XSendEvent(event.xconfigure.display, event.xconfigure.window, False,
- StructureNotifyMask, &event);
-#if 0//def DEBUG
- printf("Sent synthetic ConfigureNotify %d,%d %d,%d to 0x%lx\n",
- event.xconfigure.x, event.xconfigure.y, event.xconfigure.width,
- event.xconfigure.height, event.xconfigure.window);
-#endif
- }
- }
-}
-
-void Client::close()
-{
- XEvent ce;
-
- if (!(_functions & Func_Close)) return;
-
- // XXX: itd be cool to do timeouts and shit here for killing the client's
- // process off
- // like... if the window is around after 5 seconds, then the close button
- // turns a nice red, and if this function is called again, the client is
- // explicitly killed.
-
- ce.xclient.type = ClientMessage;
- ce.xclient.message_type = otk::Property::atoms.wm_protocols;
- ce.xclient.display = **otk::display;
- ce.xclient.window = _window;
- ce.xclient.format = 32;
- ce.xclient.data.l[0] = otk::Property::atoms.wm_delete_window;
- ce.xclient.data.l[1] = CurrentTime;
- ce.xclient.data.l[2] = 0l;
- ce.xclient.data.l[3] = 0l;
- ce.xclient.data.l[4] = 0l;
- XSendEvent(**otk::display, _window, false, NoEventMask, &ce);
-}
-
-void Client::changeState()
-{
- unsigned long state[2];
- state[0] = _wmstate;
- state[1] = None;
- otk::Property::set(_window, otk::Property::atoms.wm_state,
- otk::Property::atoms.wm_state, state, 2);
-
- Atom netstate[10];
- int num = 0;
- if (_modal)
- netstate[num++] = otk::Property::atoms.net_wm_state_modal;
- if (_shaded)
- netstate[num++] = otk::Property::atoms.net_wm_state_shaded;
- if (_iconic)
- netstate[num++] = otk::Property::atoms.net_wm_state_hidden;
- if (_skip_taskbar)
- netstate[num++] = otk::Property::atoms.net_wm_state_skip_taskbar;
- if (_skip_pager)
- netstate[num++] = otk::Property::atoms.net_wm_state_skip_pager;
- if (_fullscreen)
- netstate[num++] = otk::Property::atoms.net_wm_state_fullscreen;
- if (_max_vert)
- netstate[num++] = otk::Property::atoms.net_wm_state_maximized_vert;
- if (_max_horz)
- netstate[num++] = otk::Property::atoms.net_wm_state_maximized_horz;
- if (_above)
- netstate[num++] = otk::Property::atoms.net_wm_state_above;
- if (_below)
- netstate[num++] = otk::Property::atoms.net_wm_state_below;
- otk::Property::set(_window, otk::Property::atoms.net_wm_state,
- otk::Property::atoms.atom, netstate, num);
-
- calcLayer();
-
- if (frame)
- frame->adjustState();
-}
-
-void Client::changeAllowedActions(void)
-{
- Atom actions[9];
- int num = 0;
-
- actions[num++] = otk::Property::atoms.net_wm_action_change_desktop;
-
- if (_functions & Func_Shade)
- actions[num++] = otk::Property::atoms.net_wm_action_shade;
- if (_functions & Func_Close)
- actions[num++] = otk::Property::atoms.net_wm_action_close;
- if (_functions & Func_Move)
- actions[num++] = otk::Property::atoms.net_wm_action_move;
- if (_functions & Func_Iconify)
- actions[num++] = otk::Property::atoms.net_wm_action_minimize;
- if (_functions & Func_Resize)
- actions[num++] = otk::Property::atoms.net_wm_action_resize;
- if (_functions & Func_Fullscreen)
- actions[num++] = otk::Property::atoms.net_wm_action_fullscreen;
- if (_functions & Func_Maximize) {
- actions[num++] = otk::Property::atoms.net_wm_action_maximize_horz;
- actions[num++] = otk::Property::atoms.net_wm_action_maximize_vert;
- }
-
- otk::Property::set(_window, otk::Property::atoms.net_wm_allowed_actions,
- otk::Property::atoms.atom, actions, num);
-
- // make sure the window isn't breaking any rules now
-
- if (!(_functions & Func_Shade) && _shaded)
- if (frame) shade(false);
- else _shaded = false;
- if (!(_functions & Func_Iconify) && _iconic)
- if (frame) setDesktop(openbox->screen(_screen)->desktop());
- else _iconic = false;
- if (!(_functions & Func_Fullscreen) && _fullscreen)
- if (frame) fullscreen(false);
- else _fullscreen = false;
- if (!(_functions & Func_Maximize) && (_max_horz || _max_vert))
- if (frame) maximize(false, 0);
- else _max_vert = _max_horz = false;
-}
-
-void Client::remaximize()
-{
- int dir;
- if (_max_horz && _max_vert)
- dir = 0;
- else if (_max_horz)
- dir = 1;
- else if (_max_vert)
- dir = 2;
- else
- return; // not maximized
- _max_horz = _max_vert = false;
- maximize(true, dir, false);
-}
-
-void Client::applyStartupState()
-{
- // these are in a carefully crafted order..
-
- if (_iconic) {
- _iconic = false;
- iconify(true);
- }
- if (_fullscreen) {
- _fullscreen = false;
- fullscreen(true, false);
- }
- if (_shaded) {
- _shaded = false;
- shade(true);
- }
- if (_urgent)
- fireUrgent();
-
- if (_max_vert && _max_horz) {
- _max_vert = _max_horz = false;
- maximize(true, 0, false);
- } else if (_max_vert) {
- _max_vert = false;
- maximize(true, 2, false);
- } else if (_max_horz) {
- _max_horz = false;
- maximize(true, 1, false);
- }
-
- if (_skip_taskbar); // nothing to do for this
- if (_skip_pager); // nothing to do for this
- if (_modal); // nothing to do for this
- if (_above); // nothing to do for this
- if (_below); // nothing to do for this
-}
-
-void Client::fireUrgent()
-{
- // call the python UrgentWindow callbacks
- EventData data(_screen, this, EventAction::UrgentWindow, 0);
- openbox->bindings()->fireEvent(&data);
-}
-
-void Client::shade(bool shade)
-{
- if (!(_functions & Func_Shade) || // can't
- _shaded == shade) return; // already done
-
- // when we're iconic, don't change the wmstate
- if (!_iconic)
- _wmstate = shade ? IconicState : NormalState;
- _shaded = shade;
- changeState();
- frame->adjustSize();
-}
-
-void Client::maximize(bool max, int dir, bool savearea)
-{
- assert(dir == 0 || dir == 1 || dir == 2);
- if (!(_functions & Func_Maximize)) return; // can't
-
- // check if already done
- if (max) {
- if (dir == 0 && _max_horz && _max_vert) return;
- if (dir == 1 && _max_horz) return;
- if (dir == 2 && _max_vert) return;
- } else {
- if (dir == 0 && !_max_horz && !_max_vert) return;
- if (dir == 1 && !_max_horz) return;
- if (dir == 2 && !_max_vert) return;
- }
-
- const otk::Rect &a = openbox->screen(_screen)->area(_desktop);
- int x = frame->area().x(), y = frame->area().y(),
- w = _area.width(), h = _area.height();
-
- if (max) {
- if (savearea) {
- long dimensions[4];
- long *readdim;
- unsigned long n = 4;
-
- dimensions[0] = x;
- dimensions[1] = y;
- dimensions[2] = w;
- dimensions[3] = h;
-
- // get the property off the window and use it for the dimentions we are
- // already maxed on
- if (otk::Property::get(_window, otk::Property::atoms.openbox_premax,
- otk::Property::atoms.cardinal, &n,
- (long unsigned**) &readdim)) {
- if (n == 4) {
- if (_max_horz) {
- dimensions[0] = readdim[0];
- dimensions[2] = readdim[2];
- }
- if (_max_vert) {
- dimensions[1] = readdim[1];
- dimensions[3] = readdim[3];
- }
- }
- delete readdim;
- }
-
- otk::Property::set(_window, otk::Property::atoms.openbox_premax,
- otk::Property::atoms.cardinal,
- (long unsigned*)dimensions, 4);
- }
- if (dir == 0 || dir == 1) { // horz
- x = a.x();
- w = a.width();
- }
- if (dir == 0 || dir == 2) { // vert
- y = a.y();
- h = a.height() - frame->size().top - frame->size().bottom;
- }
- } else {
- long *dimensions;
- long unsigned n = 4;
-
- if (otk::Property::get(_window, otk::Property::atoms.openbox_premax,
- otk::Property::atoms.cardinal, &n,
- (long unsigned**) &dimensions)) {
- if (n == 4) {
- if (dir == 0 || dir == 1) { // horz
- x = (signed int)dimensions[0];
- w = (signed int)dimensions[2];
- }
- if (dir == 0 || dir == 2) { // vert
- y = (signed int)dimensions[1];
- h = (signed int)dimensions[3];
- }
- }
- delete dimensions;
- } else {
- // pick some fallbacks...
- if (dir == 0 || dir == 1) { // horz
- x = a.x() + a.width() / 4;
- w = a.width() / 2;
- }
- if (dir == 0 || dir == 2) { // vert
- y = a.y() + a.height() / 4;
- h = a.height() / 2;
- }
- }
- }
-
- if (dir == 0 || dir == 1) // horz
- _max_horz = max;
- if (dir == 0 || dir == 2) // vert
- _max_vert = max;
-
- if (!_max_horz && !_max_vert)
- otk::Property::erase(_window, otk::Property::atoms.openbox_premax);
-
- changeState(); // change the state hints on the client
-
- frame->frameGravity(x, y); // figure out where the client should be going
- internal_resize(TopLeft, w, h, true, x, y);
-}
-
-void Client::fullscreen(bool fs, bool savearea)
-{
- static FunctionFlags saved_func;
- static DecorationFlags saved_decor;
-
- if (!(_functions & Func_Fullscreen) || // can't
- _fullscreen == fs) return; // already done
-
- _fullscreen = fs;
- changeState(); // change the state hints on the client
-
- int x = _area.x(), y = _area.y(), w = _area.width(), h = _area.height();
-
- if (fs) {
- // save the functions and remove them
- saved_func = _functions;
- _functions = _functions & (Func_Close | Func_Fullscreen | Func_Iconify);
- // save the decorations and remove them
- saved_decor = _decorations;
- _decorations = 0;
- if (savearea) {
- long dimensions[4];
- dimensions[0] = _area.x();
- dimensions[1] = _area.y();
- dimensions[2] = _area.width();
- dimensions[3] = _area.height();
- otk::Property::set(_window, otk::Property::atoms.openbox_premax,
- otk::Property::atoms.cardinal,
- (long unsigned*)dimensions, 4);
- }
- const otk::ScreenInfo *info = otk::display->screenInfo(_screen);
- x = 0;
- y = 0;
- w = info->size().width();
- h = info->size().height();
- } else {
- _functions = saved_func;
- _decorations = saved_decor;
-
- long *dimensions;
- long unsigned n = 4;
-
- if (otk::Property::get(_window, otk::Property::atoms.openbox_premax,
- otk::Property::atoms.cardinal, &n,
- (long unsigned**) &dimensions)) {
- if (n == 4) {
- x = dimensions[0];
- y = dimensions[1];
- w = dimensions[2];
- h = dimensions[3];
- }
- delete dimensions;
- } else {
- // pick some fallbacks...
- const otk::Rect &a = openbox->screen(_screen)->area(_desktop);
- x = a.x() + a.width() / 4;
- y = a.y() + a.height() / 4;
- w = a.width() / 2;
- h = a.height() / 2;
- }
- }
-
- changeAllowedActions(); // based on the new _functions
-
- // when fullscreening, don't obey things like increments, fill the screen
- internal_resize(TopLeft, w, h, !fs, x, y);
-
- // raise (back) into our stacking layer
- openbox->screen(_screen)->raiseWindow(this);
-
- // try focus us when we go into fullscreen mode
- if (fs) focus();
-}
-
-void Client::iconify(bool iconic, bool curdesk)
-{
- if (_iconic == iconic) return; // nothing to do
-
-#ifdef DEBUG
- printf("%sconifying window: 0x%lx\n", (iconic ? "I" : "Uni"), _window);
-#endif
-
- _iconic = iconic;
-
- if (_iconic) {
- _wmstate = IconicState;
- ignore_unmaps++;
- // we unmap the client itself so that we can get MapRequest events, and
- // because the ICCCM tells us to!
- XUnmapWindow(**otk::display, _window);
- } else {
- if (curdesk)
- setDesktop(openbox->screen(_screen)->desktop());
- _wmstate = NormalState;
- XMapWindow(**otk::display, _window);
- }
- changeState();
- showhide();
- openbox->screen(_screen)->updateStruts();
-}
-
-void Client::disableDecorations(DecorationFlags flags)
-{
- _disabled_decorations = flags;
- setupDecorAndFunctions();
-}
-
-void Client::installColormap(bool install) const
-{
- XWindowAttributes wa;
- if (XGetWindowAttributes(**otk::display, _window, &wa)) {
- if (install)
- XInstallColormap(**otk::display, wa.colormap);
- else
- XUninstallColormap(**otk::display, wa.colormap);
- }
-}
-
-Client *Client::searchModalTree(Client *node, Client *skip)
-{
- List::const_iterator it, end = node->_transients.end();
- Client *ret;
-
- for (it = node->_transients.begin(); it != end; ++it) {
- if (*it == skip) continue; // circular?
- if ((ret = searchModalTree(*it, skip))) return ret; // got one
- if ((*it)->_modal) return *it; // got one
- }
- return 0;
-}
-
-Client *Client::findModalChild()
-{
- return searchModalTree(this, this);
-}
-
-
-bool Client::focus()
-{
- // if we have a modal child, then focus it, not us
- Client *c = findModalChild();
- if (c) return c->focus();
-
- // won't try focus if the client doesn't want it, or if the window isn't
- // visible on the screen
- if (!(frame->visible() && (_can_focus || _focus_notify))) return false;
-
- // do a check to see if the window has already been unmapped or destroyed
- // do this intelligently while watching out for unmaps we've generated
- // (ignore_unmaps > 0)
- XEvent ev;
- if (XCheckTypedWindowEvent(**otk::display, _window, DestroyNotify, &ev)) {
- XPutBackEvent(**otk::display, &ev);
- return false;
- }
- while (XCheckTypedWindowEvent(**otk::display, _window, UnmapNotify, &ev)) {
- if (ignore_unmaps) {
- unmapHandler(ev.xunmap);
- } else {
- XPutBackEvent(**otk::display, &ev);
- return false;
- }
- }
-
- if (_can_focus)
- XSetInputFocus(**otk::display, _window,
- RevertToNone, CurrentTime);
-
- if (_focus_notify) {
- XEvent ce;
- ce.xclient.type = ClientMessage;
- ce.xclient.message_type = otk::Property::atoms.wm_protocols;
- ce.xclient.display = **otk::display;
- ce.xclient.window = _window;
- ce.xclient.format = 32;
- ce.xclient.data.l[0] = otk::Property::atoms.wm_take_focus;
- ce.xclient.data.l[1] = openbox->lastTime();
- ce.xclient.data.l[2] = 0l;
- ce.xclient.data.l[3] = 0l;
- ce.xclient.data.l[4] = 0l;
- XSendEvent(**otk::display, _window, False, NoEventMask, &ce);
- }
-
- XSync(**otk::display, False);
- return true;
-}
-
-
-void Client::unfocus() const
-{
- assert(openbox->focusedClient() == this);
- openbox->setFocusedClient(0);
-}
-
-
-void Client::focusHandler(const XFocusChangeEvent &e)
-{
-#ifdef DEBUG
-// printf("FocusIn for 0x%lx\n", e.window);
-#endif // DEBUG
-
- otk::EventHandler::focusHandler(e);
-
- _focused = true;
- frame->adjustFocus();
-
- calcLayer(); // focus state can affect the stacking layer
-
- openbox->setFocusedClient(this);
-}
-
-
-void Client::unfocusHandler(const XFocusChangeEvent &e)
-{
-#ifdef DEBUG
-// printf("FocusOut for 0x%lx\n", e.window);
-#endif // DEBUG
-
- otk::EventHandler::unfocusHandler(e);
-
- _focused = false;
- frame->adjustFocus();
-
- calcLayer(); // focus state can affect the stacking layer
-
- if (openbox->focusedClient() == this)
- openbox->setFocusedClient(0);
-}
-
-
-void Client::configureRequestHandler(const XConfigureRequestEvent &ec)
-{
-#ifdef DEBUG
- printf("ConfigureRequest for 0x%lx\n", ec.window);
-#endif // DEBUG
-
- otk::EventHandler::configureRequestHandler(ec);
-
- // compress these
- XConfigureRequestEvent e = ec;
- XEvent ev;
- while (XCheckTypedWindowEvent(**otk::display, window(), ConfigureRequest,
- &ev)) {
- // XXX if this causes bad things.. we can compress config req's with the
- // same mask.
- e.value_mask |= ev.xconfigurerequest.value_mask;
- if (ev.xconfigurerequest.value_mask & CWX)
- e.x = ev.xconfigurerequest.x;
- if (ev.xconfigurerequest.value_mask & CWY)
- e.y = ev.xconfigurerequest.y;
- if (ev.xconfigurerequest.value_mask & CWWidth)
- e.width = ev.xconfigurerequest.width;
- if (ev.xconfigurerequest.value_mask & CWHeight)
- e.height = ev.xconfigurerequest.height;
- if (ev.xconfigurerequest.value_mask & CWBorderWidth)
- e.border_width = ev.xconfigurerequest.border_width;
- if (ev.xconfigurerequest.value_mask & CWStackMode)
- e.detail = ev.xconfigurerequest.detail;
- }
-
- // if we are iconic (or shaded (fvwm does this)) ignore the event
- if (_iconic || _shaded) return;
-
- if (e.value_mask & CWBorderWidth)
- _border_width = e.border_width;
-
- // resize, then move, as specified in the EWMH section 7.7
- if (e.value_mask & (CWWidth | CWHeight)) {
- int w = (e.value_mask & CWWidth) ? e.width : _area.width();
- int h = (e.value_mask & CWHeight) ? e.height : _area.height();
-
- Corner corner;
- switch (_gravity) {
- case NorthEastGravity:
- case EastGravity:
- corner = TopRight;
- break;
- case SouthWestGravity:
- case SouthGravity:
- corner = BottomLeft;
- break;
- case SouthEastGravity:
- corner = BottomRight;
- break;
- default: // NorthWest, Static, etc
- corner = TopLeft;
- }
-
- // if moving AND resizing ...
- if (e.value_mask & (CWX | CWY)) {
- int x = (e.value_mask & CWX) ? e.x : _area.x();
- int y = (e.value_mask & CWY) ? e.y : _area.y();
- internal_resize(corner, w, h, false, x, y);
- } else // if JUST resizing...
- internal_resize(corner, w, h, false);
- } else if (e.value_mask & (CWX | CWY)) { // if JUST moving...
- int x = (e.value_mask & CWX) ? e.x : _area.x();
- int y = (e.value_mask & CWY) ? e.y : _area.y();
- internal_move(x, y);
- }
-
- if (e.value_mask & CWStackMode) {
- switch (e.detail) {
- case Below:
- case BottomIf:
- openbox->screen(_screen)->lowerWindow(this);
- break;
-
- case Above:
- case TopIf:
- default:
- openbox->screen(_screen)->raiseWindow(this);
- break;
- }
- }
-}
-
-
-void Client::unmapHandler(const XUnmapEvent &e)
-{
- if (ignore_unmaps) {
-#ifdef DEBUG
-// printf("Ignored UnmapNotify for 0x%lx (event 0x%lx)\n", e.window, e.event);
-#endif // DEBUG
- ignore_unmaps--;
- return;
- }
-
-#ifdef DEBUG
- printf("UnmapNotify for 0x%lx\n", e.window);
-#endif // DEBUG
-
- otk::EventHandler::unmapHandler(e);
-
- // this deletes us etc
- openbox->screen(_screen)->unmanageWindow(this);
-}
-
-
-void Client::destroyHandler(const XDestroyWindowEvent &e)
-{
-#ifdef DEBUG
- printf("DestroyNotify for 0x%lx\n", e.window);
-#endif // DEBUG
-
- otk::EventHandler::destroyHandler(e);
-
- // this deletes us etc
- openbox->screen(_screen)->unmanageWindow(this);
-}
-
-
-void Client::reparentHandler(const XReparentEvent &e)
-{
- // this is when the client is first taken captive in the frame
- if (e.parent == frame->plate()) return;
-
-#ifdef DEBUG
- printf("ReparentNotify for 0x%lx\n", e.window);
-#endif // DEBUG
-
- otk::EventHandler::reparentHandler(e);
-
- /*
- This event is quite rare and is usually handled in unmapHandler.
- However, if the window is unmapped when the reparent event occurs,
- the window manager never sees it because an unmap event is not sent
- to an already unmapped window.
- */
-
- // we don't want the reparent event, put it back on the stack for the X
- // server to deal with after we unmanage the window
- XEvent ev;
- ev.xreparent = e;
- XPutBackEvent(**otk::display, &ev);
-
- // this deletes us etc
- openbox->screen(_screen)->unmanageWindow(this);
-}
-
-void Client::mapRequestHandler(const XMapRequestEvent &e)
-{
-#ifdef DEBUG
- printf("MapRequest for already managed 0x%lx\n", e.window);
-#endif // DEBUG
-
- assert(_iconic); // we shouldn't be able to get this unless we're iconic
-
- // move to the current desktop (uniconify)
- iconify(false);
- // XXX: should we focus/raise the window? (basically a net_wm_active_window)
-}
-
-}
diff --git a/src/client.hh b/src/client.hh
deleted file mode 100644
index 382ab1df..00000000
--- a/src/client.hh
+++ /dev/null
@@ -1,759 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef __client_hh
-#define __client_hh
-
-/*! @file client.hh
- @brief The Client class maintains the state of a client window by handling
- property changes on the window and some client messages
-*/
-
-#include "screen.hh"
-#include "otk/strut.hh"
-#include "otk/rect.hh"
-#include "otk/eventhandler.hh"
-#include "otk/ustring.hh"
-
-extern "C" {
-#include <X11/Xlib.h>
-
-#ifdef SHAPE
-#include <X11/extensions/shape.h>
-#endif // SHAPE
-}
-
-#include <string>
-#include <list>
-
-namespace ob {
-
-class Frame;
-class Screen;
-
-struct Icon {
- unsigned long w, h;
- unsigned long *data;
-};
-
-//! The MWM Hints as retrieved from the window property
-/*!
- This structure only contains 3 elements, even though the Motif 2.0
- structure contains 5. We only use the first 3, so that is all gets defined.
-*/
-struct MwmHints {
- unsigned long flags; //!< A bitmask of Client::MwmFlags values
- unsigned long functions; //!< A bitmask of Client::MwmFunctions values
- unsigned long decorations;//!< A bitmask of Client::MwmDecorations values
- //! The number of elements in the Client::MwmHints struct
- static const unsigned int elements = 3;
-};
-
-//! Maintains the state of a client window.
-/*!
- Client maintains the state of a client window. The state consists of the
- hints that the application sets on the window, such as the title, or window
- gravity.
- <p>
- Client also manages client messages for the client window. When the
- application (or any application) requests something to be changed for the
- client, it will call the ActionHandler (for client messages) or update the
- class' member variables and call whatever is nessary to complete the
- change (such as causing a redraw of the titlebar after the title is changed).
-*/
-class Client : public otk::EventHandler {
-public:
-
- //! The frame window which decorates around the client window
- /*!
- NOTE: This should NEVER be used inside the client class's constructor!
- */
- Frame *frame;
-
- //! Holds a list of Clients
- typedef std::list<Client*> List;
-
- //! The possible stacking layers a client window can be a part of
- enum StackLayer {
- Layer_Icon, //!< 0 - iconified windows, in any order at all
- Layer_Desktop, //!< 1 - desktop windows
- Layer_Below, //!< 2 - normal windows w/ below
- Layer_Normal, //!< 3 - normal windows
- Layer_Above, //!< 4 - normal windows w/ above
- Layer_Top, //!< 5 - always-on-top-windows (docks?)
- Layer_Fullscreen, //!< 6 - fullscreeen windows
- Layer_Internal, //!< 7 - openbox windows/menus
- NUM_LAYERS
- };
-
- //! Corners of the client window, used for anchor positions
- enum Corner { TopLeft,
- TopRight,
- BottomLeft,
- BottomRight };
-
- //! Possible window types
- enum WindowType { Type_Desktop, //!< A desktop (bottom-most window)
- Type_Dock, //!< A dock bar/panel window
- Type_Toolbar, //!< A toolbar window, pulled off an app
- Type_Menu, //!< An unpinned menu from an app
- Type_Utility, //!< A small utility window such as a palette
- Type_Splash, //!< A splash screen window
- Type_Dialog, //!< A dialog window
- Type_Normal //!< A normal application window
- };
-
- //! Possible flags for MWM Hints (defined by Motif 2.0)
- enum MwmFlags { MwmFlag_Functions = 1 << 0, //!< The MMW Hints define funcs
- MwmFlag_Decorations = 1 << 1 //!< The MWM Hints define decor
- };
-
- //! Possible functions for MWM Hints (defined by Motif 2.0)
- enum MwmFunctions { MwmFunc_All = 1 << 0, //!< All functions
- MwmFunc_Resize = 1 << 1, //!< Allow resizing
- MwmFunc_Move = 1 << 2, //!< Allow moving
- MwmFunc_Iconify = 1 << 3, //!< Allow to be iconfied
- MwmFunc_Maximize = 1 << 4 //!< Allow to be maximized
- //MwmFunc_Close = 1 << 5 //!< Allow to be closed
- };
-
- //! Possible decorations for MWM Hints (defined by Motif 2.0)
- enum MemDecorations { MwmDecor_All = 1 << 0, //!< All decorations
- MwmDecor_Border = 1 << 1, //!< Show a border
- MwmDecor_Handle = 1 << 2, //!< Show a handle (bottom)
- MwmDecor_Title = 1 << 3, //!< Show a titlebar
- //MwmDecor_Menu = 1 << 4, //!< Show a menu
- MwmDecor_Iconify = 1 << 5, //!< Show an iconify button
- MwmDecor_Maximize = 1 << 6 //!< Show a maximize button
- };
-
- //! The things the user can do to the client window
- enum Function { Func_Resize = 1 << 0, //!< Allow resizing
- Func_Move = 1 << 1, //!< Allow moving
- Func_Iconify = 1 << 2, //!< Allow to be iconified
- Func_Maximize = 1 << 3, //!< Allow to be maximized
- Func_Shade = 1 << 4, //!< Allow to be shaded
- Func_Fullscreen = 1 << 5, //!< Allow to be made fullscreen
- Func_Close = 1 << 6 //!< Allow to be closed
- };
- //! Holds a bitmask of Client::Function values
- typedef unsigned char FunctionFlags;
-
- //! The decorations the client window wants to be displayed on it
- enum Decoration { Decor_Titlebar = 1 << 0, //!< Display a titlebar
- Decor_Handle = 1 << 1, //!< Display a handle (bottom)
- Decor_Border = 1 << 2, //!< Display a border
- Decor_Icon = 1 << 3, //!< Display the window's icon
- Decor_Iconify = 1 << 4, //!< Display an iconify button
- Decor_Maximize = 1 << 5, //!< Display a maximize button
- //! Display a button to toggle the window's placement on
- //! all desktops
- Decor_AllDesktops = 1 << 6,
- Decor_Close = 1 << 7 //!< Display a close button
- };
- //! Holds a bitmask of Client::Decoration values
- typedef unsigned char DecorationFlags;
-
- //! The event mask to grab on client windows
- static const long event_mask = PropertyChangeMask | FocusChangeMask |
- StructureNotifyMask;
-
- //! The mask of events to not let propogate past the client
- /*!
- This makes things like xprop work on the client window, but means we have
- to explicitly grab clicks that we want.
- */
- static const long no_propagate_mask = ButtonPressMask | ButtonReleaseMask |
- ButtonMotionMask;
-
- //! The number of unmap events to ignore on the window
- int ignore_unmaps;
-
-private:
- //! The screen number on which the client resides
- int _screen;
-
- //! The actual window that this class is wrapping up
- Window _window;
-
- //! The id of the group the window belongs to
- Window _group;
-
- //! The client which this client is a transient (child) for
- Client *_transient_for;
-
- //! The clients which are transients (children) of this client
- Client::List _transients;
-
- //! The desktop on which the window resides (0xffffffff for all desktops)
- unsigned int _desktop;
-
- //! Normal window title
- otk::ustring _title;
- //! Window title when iconifiged
- otk::ustring _icon_title;
-
- //! The application that created the window
- std::string _app_name;
- //! The class of the window, can used for grouping
- std::string _app_class;
- //! The specified role of the window, used for identification
- std::string _role;
-
- //! The type of window (what its function is)
- WindowType _type;
-
- //! Position and size of the window
- /*!
- This will not always be the actual position of the window on screen, it is
- rather, the position requested by the client, to which the window's gravity
- is applied.
- */
- otk::Rect _area;
-
- //! The window's strut
- /*!
- The strut defines areas of the screen that are marked off-bounds for window
- placement. In theory, where this window exists.
- */
- otk::Strut _strut;
-
- //! The logical size of the window
- /*!
- The "logical" size of the window is refers to the user's perception of the
- size of the window, and is the value that should be displayed to the user.
- For example, with xterms, this value it the number of characters being
- displayed in the terminal, instead of the number of pixels.
- */
- otk::Size _logical_size;
-
- //! Width of the border on the window.
- /*!
- The window manager will set this to 0 while the window is being managed,
- but needs to restore it afterwards, so it is saved here.
- */
- int _border_width;
-
- //! The minimum aspect ratio the client window can be sized to.
- /*!
- A value of 0 means this is ignored.
- */
- float _min_ratio;
- //! The maximum aspect ratio the client window can be sized to.
- /*!
- A value of 0 means this is ignored.
- */
- float _max_ratio;
-
- //! The minimum size of the client window
- /*!
- If the min is > the max, then the window is not resizable
- */
- otk::Size _min_size;
- //! The maximum size of the client window
- /*!
- If the min is > the max, then the window is not resizable
- */
- otk::Size _max_size;
- //! The size of increments to resize the client window by
- otk::Size _size_inc;
- //! The base size of the client window
- /*!
- This value should be subtracted from the window's actual size when
- displaying its size to the user, or working with its min/max size
- */
- otk::Size _base_size;
-
- //! Window decoration and functionality hints
- MwmHints _mwmhints;
-
- //! Where to place the decorated window in relation to the undecorated window
- int _gravity;
-
- //! The state of the window, one of WithdrawnState, IconicState, or
- //! NormalState
- long _wmstate;
-
- //! True if the client supports the delete_window protocol
- bool _delete_window;
-
- //! Was the window's position requested by the application? if not, we should
- //! place the window ourselves when it first appears
- bool _positioned;
-
- //! Can the window receive input focus?
- bool _can_focus;
- //! Urgency flag
- bool _urgent;
- //! Notify the window when it receives focus?
- bool _focus_notify;
- //! Does the client window have the input focus?
- bool _focused;
-
- //! The window uses shape extension to be non-rectangular?
- bool _shaped;
-
- //! The window is modal, so it must be processed before any windows it is
- //! related to can be focused
- bool _modal;
- //! Only the window's titlebar is displayed
- bool _shaded;
- //! The window is iconified
- bool _iconic;
- //! The window is maximized to fill the screen vertically
- bool _max_vert;
- //! The window is maximized to fill the screen horizontally
- bool _max_horz;
- //! The window should not be displayed by pagers
- bool _skip_pager;
- //! The window should not be displayed by taskbars
- bool _skip_taskbar;
- //! The window is a 'fullscreen' window, and should be on top of all others
- bool _fullscreen;
- //! The window should be on top of other windows of the same type
- bool _above;
- //! The window should be underneath other windows of the same type
- bool _below;
-
- //! The layer in which the window will be stacked, windows in lower layers
- //! are always below windows in higher layers.
- StackLayer _layer;
-
- //! A bitmask of values in the Client::Decoration enum
- /*!
- The values in the variable are the decorations that the client wants to be
- displayed around it.
- */
- DecorationFlags _decorations;
-
- //! A bitmask of values in the Client::Decoration enum.
- /*!
- Specifies the decorations that should NOT be displayed on the client.
- */
- DecorationFlags _disabled_decorations;
-
- //! A bitmask of values in the Client::Function enum
- /*!
- The values in the variable specify the ways in which the user is allowed to
- modify this window.
- */
- FunctionFlags _functions;
-
- //! Icons for the client as specified on the client window
- Icon *_icons;
- //! The number of icons in _icons
- int _nicons;
-
- Pixmap _pixmap_icon;
- Pixmap _pixmap_icon_mask;
-
- //! Retrieves the window's initial gravity
- void getGravity();
- //! Retrieves the desktop hint's value and sets Client::_desktop
- void getDesktop();
- //! Retrieves the window's type and sets Client::_type
- void getType();
- //! Gets the MWM Hints and adjusts Client::_functions and
- //! Client::_decorations
- void getMwmHints();
- //! Gets the position and size of the window and sets Client::_area
- void getArea();
- //! Gets the net_state hint and sets the boolean flags for any states set in
- //! the hint
- void getState();
- //! Determines if the window uses the Shape extension and sets
- //! Client::_shaped
- void getShaped();
-
- //! Set up what decor should be shown on the window and what functions should
- //! be allowed (Client::_decorations and Client::_functions).
- /*!
- This also updates the NET_WM_ALLOWED_ACTIONS hint.
- */
- void setupDecorAndFunctions();
-
- //! Sets the wm_state to the specified value
- void setWMState(long state);
- //! Adjusts the window's net_state
- /*!
- This should not be called as part of the window mapping process! It is for
- use when updating the state post-mapping.<br>
- Client::applyStartupState is used to do the same things during the mapping
- process.
- */
- void setState(Atom action, long data1, long data2);
-
- //! Sends the window to the specified desktop
- void setDesktop(unsigned int desktop);
-
- //! Calculates the stacking layer for the client window
- void calcLayer();
-
- //! Update the protocols that the window supports and adjusts things if they
- //! change
- void updateProtocols();
- //! Updates the WMNormalHints and adjusts things if they change
- void updateNormalHints();
- //! Updates the WMHints and adjusts things if they change
- /*!
- @param initstate Whether to read the initial_state property from the
- WMHints. This should only be used during the mapping
- process.
- */
- void updateWMHints(bool initstate = false);
- //! Updates the window's title
- void updateTitle();
- //! Updates the window's icon title
- void updateIconTitle();
- //! Updates the window's application name and class
- void updateClass();
- //! Updates the strut for the client
- void updateStrut();
- //! Updates the window's transient status, and any parents of it
- void updateTransientFor();
- //! Updates the window's icons
- void updateIcons();
- //! Updates the window's kwm icon
- void updateKwmIcon();
-
- //! Change the client's state hints to match the class' data
- void changeState();
- //! Change the allowed actions set on the client
- void changeAllowedActions();
-
- //! Request the client to close its window.
- void close();
-
- //! Shades or unshades the client window
- /*!
- @param shade true if the window should be shaded; false if it should be
- unshaded.
- */
- void shade(bool shade);
-
- //! Recursively searches the client 'tree' for a modal client, always skips
- //! the topmost node (the window you're starting with).
- Client *Client::searchModalTree(Client *node, Client *skip);
-
- //! Recursively searches the client 'tree' for a focused client, always skips
- //! the topmost node (the window you're starting with).
- Client *Client::searchFocusTree(Client *node, Client *skip);
-
- //! Fires the urgent callbacks which lets the user do what they want with
- //! urgent windows
- void fireUrgent();
-
- //! Fullscreen's or unfullscreen's the client window
- /*!
- @param fs true if the window should be made fullscreen; false if it should
- be returned to normal state.
- @param savearea true to have the client's current size and position saved;
- otherwise, they are not. You should not save when mapping a
- new window that is set to fullscreen. This has no effect
- when restoring a window from fullscreen.
- */
- void fullscreen(bool fs, bool savearea = true);
-
- //! Iconifies or uniconifies the client window
- /*!
- @param iconic true if the window should be iconified; false if it should be
- restored.
- @param curdesk If iconic is false, then this determines if the window will
- be uniconified to the current viewable desktop (true) or to
- its previous desktop (false)
- */
- void iconify(bool iconic, bool curdesk = true);
-
- //! Maximize or unmaximize the client window
- /*!
- @param max true if the window should be maximized; false if it should be
- returned to normal size.
- @param dir 0 to set both horz and vert, 1 to set horz, 2 to set vert.
- @param savearea true to have the client's current size and position saved;
- otherwise, they are not. You should not save when mapping a
- new window that is set to fullscreen. This has no effect
- when unmaximizing a window.
- */
- void maximize(bool max, int dir, bool savearea = true);
-
- //! Internal version of the Client::move function
- /*!
- @param x The X coordinate to move to.
- @param y The Y coordinate to move to.
- @param final true if this is the final move, false if there are more move
- events coming. The client is not notified of the move when
- final is false.
- */
- void internal_move(int x, int y, bool final = true);
- //! Internal version of the Client::resize function
- /*!
- This also maintains things like the client's minsize, and size increments.
- @param anchor The corner to keep in the same position when resizing.
- @param w The width component of the new size for the client.
- @param h The height component of the new size for the client.
- @param user Specifies whether this is a user-requested change or a
- program requested change.
- @param x An optional X coordinate to which the window will be moved
- after resizing.
- @param y An optional Y coordinate to which the window will be moved
- after resizing.
- The x and y coordinates must both be sepcified together, or they will have
- no effect. When they are specified, the anchor is ignored.
- */
- void internal_resize(Corner anchor, int w, int h,
- bool user = true, int x = INT_MIN, int y = INT_MIN);
-
- //! Removes or reapplies the client's border to its window
- /*!
- Used when managing and unmanaging a window.
- @param addborder true if adding the border to the client; false if removing
- from the client
- */
- void toggleClientBorder(bool addborder);
-
- //! Applies the states requested when the window mapped
- /*!
- This should be called only once, during the window mapping process. It
- applies things like maximized, and fullscreen.
- */
- void applyStartupState();
-
-public:
- //! Constructs a new Client object around a specified window id
- /*!
- @param window The window id that the Client class should handle
- @param screen The screen on which the window resides
- */
- Client(int screen, Window window);
- //! Destroys the Client object
- virtual ~Client();
-
- //! Returns the screen on which the clien resides
- inline int screen() const { return _screen; }
-
- //! Returns the window id that the Client object is handling
- inline Window window() const { return _window; }
-
- //! Returns the type of the window, one of the Client::WindowType values
- inline WindowType type() const { return _type; }
- //! Returns if the window should be treated as a normal window.
- /*!
- Some windows (desktops, docks, splash screens) have special rules applied
- to them in a number of places regarding focus or user interaction.
- */
- inline bool normal() const {
- return ! (_type == Type_Desktop || _type == Type_Dock ||
- _type == Type_Splash);
- }
-
- //! Returns the desktop on which the window resides
- /*!
- This value is a 0-based index.<br>
- A value of 0xffffffff indicates that the window exists on all desktops.
- */
- inline unsigned int desktop() const { return _desktop; }
- //! Returns the window's title
- inline const otk::ustring &title() const { return _title; }
- //! Returns the window's title when it is iconified
- inline const otk::ustring &iconTitle() const { return _title; }
- //! Returns the application's name to whom the window belongs
- inline const std::string &appName() const { return _app_name; }
- //! Returns the class of the window
- inline const std::string &appClass() const { return _app_class; }
- //! Returns the program-specified role of the window
- inline const std::string &role() const { return _role; }
- //! Returns if the window can be focused
- /*!
- @return true if the window can receive focus; otherwise, false
- */
- inline bool canFocus() const { return _can_focus; }
- //! Returns if the window has indicated that it needs urgent attention
- inline bool urgent() const { return _urgent; }
- //! Returns if the window wants to be notified when it receives focus
- inline bool focusNotify() const { return _focus_notify; }
- //! Returns if the window is the focused window
- inline bool focused() const { return _focused; }
- //! Returns if the window uses the Shape extension
- inline bool shaped() const { return _shaped; }
- //! Returns the window's gravity
- /*!
- This value determines where to place the decorated window in relation to
- its position without decorations.<br>
- One of: NorthWestGravity, SouthWestGravity, EastGravity, ...,
- SouthGravity, StaticGravity, ForgetGravity
- */
- inline int gravity() const { return _gravity; }
- //! Returns if the application requested the initial position for the window
- /*!
- If the application did not request a position (this function returns false)
- then the window should be placed intelligently by the window manager
- initially
- */
- inline bool positionRequested() const { return _positioned; }
- //! Returns the decorations that the client window wishes to be displayed on
- //! it
- inline DecorationFlags decorations() const { return _decorations; }
- //! Returns the decorations that the user has requested to be disabled on the
- //! client
- inline DecorationFlags disabledDecorations() const
- { return _disabled_decorations; }
- //! Returns the functions that the user can perform on the window
- inline FunctionFlags functions() const { return _functions; }
-
- //! Return the client this window is transient for
- inline Client *transientFor() const { return _transient_for; }
-
- //! Returns if the window is modal
- /*!
- If the window is modal, then no other windows that it is related to can get
- focus while it exists/remains modal.
- */
- inline bool modal() const { return _modal; }
- //! The window should not be displayed by pagers
- inline bool skipPager() const { return _skip_pager; }
- //! The window should not be displayed by taskbars
- inline bool skipTaskbar() const { return _skip_taskbar; }
- //! Returns if the window is shaded
- /*!
- When the window is shaded, only its titlebar is visible.
- */
- inline bool shaded() const { return _shaded; }
- //! Returns if the window is in fullscreen mode
- inline bool fullscreen() const { return _fullscreen; }
- //! Returns if the window is iconified
- /*!
- When the window is iconified, it is not visible at all (except in iconbars/
- panels/etc that want to show lists of iconified windows
- */
- inline bool iconic() const { return _iconic; }
- //! Returns if the window is maximized vertically
- inline bool maxVert() const { return _max_vert; }
- //! Returns if the window is maximized horizontally
- inline bool maxHorz() const { return _max_horz; }
- //! Returns the window's stacking layer
- inline StackLayer layer() const { return _layer; }
-
- //! Returns the logical size of the window
- /*!
- The "logical" size of the window is refers to the user's perception of the
- size of the window, and is the value that should be displayed to the user.
- For example, with xterms, this value it the number of characters being
- displayed in the terminal, instead of the number of pixels.
- */
- const otk::Size &logicalSize() const { return _logical_size; }
-
- //! Returns the position and size of the client relative to the root window
- /*!
- Note that this value is *not* the size and position of the window's
- frame, though the position will often line up.<br>
- If you want the frame's area, use Frame::area() instead.
- */
- inline const otk::Rect &area() const { return _area; }
-
- //! Returns the client's strut definition
- inline const otk::Strut &strut() const { return _strut; }
-
- //! Returns an icon for the window
- /*!
- The icon chosen will be the smallest icon available that is still bigger or
- equal to the specified Size.<br>
- If none that meet the requirements is found, the largest icon that is
- smaller than the specified size will be returned.
- */
- const Icon *icon(const otk::Size &s) const;
-
- //! Returns the pixmap for the pixmap icon specified on the window (or None)
- /*!
- The icon given by Client::icon should take precedence over this icon/mask.
- */
- Pixmap pixmapIcon() const { return _pixmap_icon; }
- //! Returns the mask for the pixmap icon specified on the window (or None)
- /*!
- The icon given by Client::icon should take precedence over this icon/mask.
- */
- Pixmap pixmapIconMask() const { return _pixmap_icon_mask; }
-
- //! Move the window (actually, its frame) to a position.
- /*!
- This moves the window so that the top-left corner of its frame will be at
- the position specified.
- @param x The X coordinate to move to.
- @param y The Y coordinate to move to.
- @param final true if this is the final move, false if there are more move
- events coming. The client is not notified of the move when
- final is false.
- */
- void move(int x, int y, bool final = true);
-
- //! Resizes the client window, anchoring it in a given corner
- /*!
- This also maintains things like the client's minsize, and size increments.
- @param anchor The corner to keep in the same position when resizing.
- @param w The width component of the new size for the client.
- @param h The height component of the new size for the client.
- */
- void resize(Corner anchor, int w, int h);
-
- //! Reapplies the maximized state to the window
- /*!
- Use this to make the window readjust its maximized size to new
- surroundings (struts, etc).
- */
- void remaximize();
-
- //! Shows the window if it should be shown, or hides it
- /*!
- Used when changing desktops, the window's state, etc.
- */
- void showhide();
-
- //! Choose a mask of decorations to not display on the client
- /*!
- Pass a value of 0 to the function to turn all decorations back on. Note
- that you cannot add decorations to a window with this, you can only remove
- decorations that would otherwise have been displayed.
- @param flags The mask of values from Client::Decoration to specify which
- decorations should not be displayed.
- */
- void disableDecorations(DecorationFlags flags);
-
- //! Return a modal child of the client window
- /*!
- @return A modal child of the client window, or 0 if none was found.
- */
- Client *findModalChild();
-
- //! Attempt to focus the client window
- bool focus();
-
- //! Remove focus from the client window
- void unfocus() const;
-
- //! Validate client, by making sure no Destroy or Unmap events exist in
- //! the event queue for the window.
- /*!
- @return true if the client is valid; false if the client has already
- been unmapped/destroyed, and so is invalid.
- */
- bool validate() const;
-
- void installColormap(bool install) const;
-
- virtual void focusHandler(const XFocusChangeEvent &e);
- virtual void unfocusHandler(const XFocusChangeEvent &e);
- virtual void propertyHandler(const XPropertyEvent &e);
- virtual void clientMessageHandler(const XClientMessageEvent &e);
- virtual void configureRequestHandler(const XConfigureRequestEvent &e);
- virtual void unmapHandler(const XUnmapEvent &e);
- virtual void destroyHandler(const XDestroyWindowEvent &e);
- virtual void reparentHandler(const XReparentEvent &e);
- virtual void mapRequestHandler(const XMapRequestEvent &e);
-#if defined(SHAPE)
- virtual void shapeHandler(const XShapeEvent &e);
-#endif // SHAPE
-
- friend void Screen::manageWindow(Window);
- friend void Screen::unmanageWindow(Client *);
-};
-
-}
-
-#endif // __client_hh
diff --git a/src/config.cc b/src/config.cc
deleted file mode 100644
index 5c6ddfe9..00000000
--- a/src/config.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#include "config.h"
-
-/*
- python_get_stringlist("DESKTOP_NAMES", &desktop_names);
-
- python_get_string("THEME", &theme);
- // initialize the screen's style
- otk::RenderStyle::setStyle(_screen, theme);
- // draw the root window
- otk::bexec("obsetroot " + otk::RenderStyle::style(_screen)->rootArgs(),
- info->displayString());
-
-
- if (!python_get_string("TITLEBAR_LAYOUT", &titlebar_layout)) {
- fprintf(stderr, _("Unable to load config.%s\n"), "TITLEBAR_LAYOUT");
- ::exit(1);
- }
-
- if (!python_get_long("DOUBLE_CLICK_DELAY", &double_click_delay)) {
- fprintf(stderr, _("Unable to load config.%s\n"), "DOUBLE_CLICK_DELAY");
- ::exit(1);
- }
- if (!python_get_long("DRAG_THRESHOLD", &drag_threshold)) {
- fprintf(stderr, _("Unable to load config.%s\n"), "DRAG_THRESHOLD");
- ::exit(1);
- }
- if (!python_get_long("NUMBER_OF_DESKTOPS", (long*)&num_desktops)) {
- fprintf(stderr, _("Unable to load config.%s\n"), "NUMBER_OF_DESKTOPS");
- ::exit(1);
- }
-
- // Set the net_desktop_names property
- otk::Property::set(root,
- otk::Property::atoms.net_desktop_names,
- otk::Property::utf8, desktop_names);
- // the above set() will cause screen::updateDesktopNames to fire right away
- // so we have a list of desktop names
-
- XEvent ce;
- ce.xclient.type = ClientMessage;
- ce.xclient.message_type = otk::Property::atoms.net_number_of_desktops;
- ce.xclient.display = **otk::display;
- ce.xclient.window = root;
- ce.xclient.format = 32;
- ce.xclient.data.l[0] = num_desktops;
- XSendEvent(**otk::display, root, False,
- SubstructureNotifyMask | SubstructureRedirectMask, &ce);
-}
-
-Config::Config(int screen)
- : _screen(screen)
-{
-}
-
-Config::~Config()
-{
-}
-
-*/
diff --git a/src/config.hh b/src/config.hh
deleted file mode 100644
index 4f664c19..00000000
--- a/src/config.hh
+++ /dev/null
@@ -1,14 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef __config_hh
-#define __config_hh
-
-/*! @file config.hh
- @brief The Config class contains functions for accessing config variables
- in the scripts.
-*/
-
-namespace ob {
-
-}
-
-#endif // __config_hh
diff --git a/src/frame.cc b/src/frame.cc
deleted file mode 100644
index 4e77d106..00000000
--- a/src/frame.cc
+++ /dev/null
@@ -1,959 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#include "config.h"
-
-extern "C" {
-#ifdef SHAPE
-#include <X11/extensions/shape.h>
-#endif // SHAPE
-}
-
-#include "frame.hh"
-#include "config.hh"
-#include "openbox.hh"
-#include "otk/display.hh"
-#include "otk/surface.hh"
-
-#include <string>
-#include <cassert>
-
-namespace ob {
-
-const long Frame::event_mask;
-
-Window createWindow(const otk::ScreenInfo *info, Window parent,
- unsigned long mask, XSetWindowAttributes *attrib)
-{
- return XCreateWindow(**otk::display, parent, 0, 0, 1, 1, 0,
- info->depth(), InputOutput, info->visual(),
- mask, attrib);
-
-}
-
-Frame::Frame(Client *client)
- : _client(client),
- _visible(false),
- _plate(0),
- _title(0),
- _label(0),
- _handle(0),
- _lgrip(0),
- _rgrip(0),
- _max(0),
- _desk(0),
- _iconify(0),
- _icon(0),
- _close(0),
- _frame_sur(0),
- _title_sur(0),
- _label_sur(0),
- _handle_sur(0),
- _grip_sur(0),
- _max_sur(0),
- _desk_sur(0),
- _iconify_sur(0),
- _icon_sur(0),
- _close_sur(0),
- _max_press(false),
- _desk_press(false),
- _iconify_press(false),
- _icon_press(false),
- _close_press(false),
- _press_button(0)
-{
- assert(client);
-
- XSetWindowAttributes attrib;
- unsigned long mask;
- const otk::ScreenInfo *info = otk::display->screenInfo(client->screen());
-
- // create all of the decor windows (except title bar buttons)
- mask = CWOverrideRedirect | CWEventMask;
- attrib.event_mask = Frame::event_mask;
- attrib.override_redirect = true;
- _frame = createWindow(info, info->rootWindow(), mask, &attrib);
-
- mask = 0;
- _plate = createWindow(info, _frame, mask, &attrib);
- mask = CWEventMask;
- attrib.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
- ExposureMask);
- _title = createWindow(info, _frame, mask, &attrib);
- _label = createWindow(info, _title, mask, &attrib);
- _max = createWindow(info, _title, mask, &attrib);
- _close = createWindow(info, _title, mask, &attrib);
- _desk = createWindow(info, _title, mask, &attrib);
- _icon = createWindow(info, _title, mask, &attrib);
- _iconify = createWindow(info, _title, mask, &attrib);
- _handle = createWindow(info, _frame, mask, &attrib);
- mask |= CWCursor;
- attrib.cursor = openbox->cursors().ll_angle;
- _lgrip = createWindow(info, _handle, mask, &attrib);
- attrib.cursor = openbox->cursors().lr_angle;
- _rgrip = createWindow(info, _handle, mask, &attrib);
-
- // the other stuff is shown based on decor settings
- XMapWindow(**otk::display, _plate);
- XMapWindow(**otk::display, _lgrip);
- XMapWindow(**otk::display, _rgrip);
- XMapWindow(**otk::display, _label);
-
- applyStyle(*otk::RenderStyle::style(_client->screen()));
-
- _layout = "ITMC";
- python_get_string("titlebar_layout", &_layout);
-
- // register all of the windows with the event dispatcher
- Window *w = allWindows();
- for (unsigned int i = 0; w[i]; ++i)
- openbox->registerHandler(w[i], this);
- delete [] w;
-}
-
-Frame::~Frame()
-{
- // unregister all of the windows with the event dispatcher
- Window *w = allWindows();
- for (unsigned int i = 0; w[i]; ++i)
- openbox->clearHandler(w[i]);
- delete [] w;
-
- XDestroyWindow(**otk::display, _rgrip);
- XDestroyWindow(**otk::display, _lgrip);
- XDestroyWindow(**otk::display, _handle);
- XDestroyWindow(**otk::display, _max);
- XDestroyWindow(**otk::display, _icon);
- XDestroyWindow(**otk::display, _iconify);
- XDestroyWindow(**otk::display, _desk);
- XDestroyWindow(**otk::display, _close);
- XDestroyWindow(**otk::display, _label);
- XDestroyWindow(**otk::display, _title);
- XDestroyWindow(**otk::display, _frame);
-
- if (_frame_sur) delete _frame_sur;
- if (_title_sur) delete _title_sur;
- if (_label_sur) delete _label_sur;
- if (_handle_sur) delete _handle_sur;
- if (_grip_sur) delete _grip_sur;
- if (_max_sur) delete _max_sur;
- if (_desk_sur) delete _desk_sur;
- if (_iconify_sur) delete _iconify_sur;
- if (_icon_sur) delete _icon_sur;
- if (_close_sur) delete _close_sur;
-}
-
-void Frame::show()
-{
- if (!_visible) {
- _visible = true;
- XMapWindow(**otk::display, _frame);
- }
-}
-
-void Frame::hide()
-{
- if (_visible) {
- _visible = false;
- XUnmapWindow(**otk::display, _frame);
- }
-}
-
-void Frame::buttonPressHandler(const XButtonEvent &e)
-{
- if (_press_button) return;
- _press_button = e.button;
-
- if (e.window == _max) {
- _max_press = true;
- renderMax();
- }
- if (e.window == _close) {
- _close_press = true;
- renderClose();
- }
- if (e.window == _desk) {
- _desk_press = true;
- renderDesk();
- }
- if (e.window == _iconify) {
- _iconify_press = true;
- renderIconify();
- }
- if (e.window == _icon) {
- _icon_press = true;
- renderIcon();
- }
-}
-
-void Frame::buttonReleaseHandler(const XButtonEvent &e)
-{
- if (e.button != _press_button) return;
- _press_button = 0;
-
- if (e.window == _max) {
- _max_press = false;
- renderMax();
- }
- if (e.window == _close) {
- _close_press = false;
- renderClose();
- }
- if (e.window == _desk) {
- _desk_press = false;
- renderDesk();
- }
- if (e.window == _iconify) {
- _iconify_press = false;
- renderIconify();
- }
- if (e.window == _icon) {
- _icon_press = false;
- renderIcon();
- }
-}
-
-MouseContext::MC Frame::mouseContext(Window win) const
-{
- if (win == _frame) return MouseContext::Frame;
- if (win == _title ||
- win == _label) return MouseContext::Titlebar;
- if (win == _handle) return MouseContext::Handle;
- if (win == _plate) return MouseContext::Window;
- if (win == _lgrip ||
- win == _rgrip) return MouseContext::Grip;
- if (win == _max) return MouseContext::MaximizeButton;
- if (win == _close) return MouseContext::CloseButton;
- if (win == _desk) return MouseContext::AllDesktopsButton;
- if (win == _iconify)return MouseContext::IconifyButton;
- if (win == _icon) return MouseContext::IconButton;
- return (MouseContext::MC) -1;
-}
-
-Window *Frame::allWindows() const
-{
- Window *w = new Window[12 + 1];
- unsigned int i = 0;
- w[i++] = _frame;
- w[i++] = _plate;
- w[i++] = _title;
- w[i++] = _label;
- w[i++] = _handle;
- w[i++] = _lgrip;
- w[i++] = _rgrip;
- w[i++] = _max;
- w[i++] = _desk;
- w[i++] = _close;
- w[i++] = _icon;
- w[i++] = _iconify;
- w[i] = 0;
- return w;
-}
-
-void Frame::applyStyle(const otk::RenderStyle &style)
-{
- // set static border colors
- XSetWindowBorder(**otk::display, _frame, style.frameBorderColor()->pixel());
- XSetWindowBorder(**otk::display, _title, style.frameBorderColor()->pixel());
- XSetWindowBorder(**otk::display, _handle, style.frameBorderColor()->pixel());
- XSetWindowBorder(**otk::display, _lgrip, style.frameBorderColor()->pixel());
- XSetWindowBorder(**otk::display, _rgrip, style.frameBorderColor()->pixel());
-
- // size all the fixed-size elements
- geom.font_height = style.labelFont()->height();
- if (geom.font_height < 1) geom.font_height = 1;
- geom.button_size = geom.font_height - 2;
- if (geom.button_size < 1) geom.button_size = 1;
- geom.handle_height = style.handleWidth();
- if (geom.handle_height < 1) geom.handle_height = 1;
- geom.bevel = style.bevelWidth();
-
- XResizeWindow(**otk::display, _lgrip, geom.grip_width(), geom.handle_height);
- XResizeWindow(**otk::display, _rgrip, geom.grip_width(), geom.handle_height);
-
- XResizeWindow(**otk::display, _max, geom.button_size, geom.button_size);
- XResizeWindow(**otk::display, _close, geom.button_size, geom.button_size);
- XResizeWindow(**otk::display, _desk, geom.button_size, geom.button_size);
- XResizeWindow(**otk::display, _iconify, geom.button_size, geom.button_size);
- XResizeWindow(**otk::display, _icon, geom.button_size, geom.button_size);
-}
-
-void Frame::styleChanged(const otk::RenderStyle &style)
-{
- applyStyle(style);
-
- // size/position everything
- adjustSize();
- adjustPosition();
-}
-
-void Frame::adjustFocus()
-{
- // XXX optimizations later...
- adjustSize();
-}
-
-void Frame::adjustTitle()
-{
- // XXX optimizations later...
- adjustSize();
-}
-
-static void render(int screen, const otk::Size &size, Window win,
- otk::Surface **surface,
- const otk::RenderTexture &texture, bool freedata=true)
-{
- otk::Surface *s = new otk::Surface(screen, size);
- if (texture.parentRelative())
- XSetWindowBackgroundPixmap(**otk::display, win, ParentRelative);
- else {
- otk::display->renderControl(screen)->drawBackground(*s, texture);
- XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap());
- }
- XClearWindow(**otk::display, win);
- if (*surface) delete *surface;
- if (freedata) s->freePixelData();
- *surface = s;
-}
-
-void Frame::adjustSize()
-{
- _decorations = _client->decorations();
- const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
-
- if (_decorations & Client::Decor_Border) {
- geom.bwidth = style->frameBorderWidth();
- geom.cbwidth = style->clientBorderWidth();
- } else {
- geom.bwidth = geom.cbwidth = 0;
- }
- _innersize.left = _innersize.top = _innersize.bottom = _innersize.right =
- geom.cbwidth;
- geom.width = _client->area().width() + geom.cbwidth * 2;
- assert(geom.width > 0);
-
- // set border widths
- XSetWindowBorderWidth(**otk::display, _plate, geom.cbwidth);
- XSetWindowBorderWidth(**otk::display, _frame, geom.bwidth);
- XSetWindowBorderWidth(**otk::display, _title, geom.bwidth);
- XSetWindowBorderWidth(**otk::display, _handle, geom.bwidth);
- XSetWindowBorderWidth(**otk::display, _lgrip, geom.bwidth);
- XSetWindowBorderWidth(**otk::display, _rgrip, geom.bwidth);
-
- // position/size and map/unmap all the windows
-
- if (_decorations & Client::Decor_Titlebar) {
- XMoveResizeWindow(**otk::display, _title, -geom.bwidth, -geom.bwidth,
- geom.width, geom.title_height());
- _innersize.top += geom.title_height() + geom.bwidth;
- XMapWindow(**otk::display, _title);
-
- // layout the title bar elements
- layoutTitle();
- } else {
- XUnmapWindow(**otk::display, _title);
- // make all the titlebar stuff not render
- _decorations &= ~(Client::Decor_Icon | Client::Decor_Iconify |
- Client::Decor_Maximize | Client::Decor_Close |
- Client::Decor_AllDesktops);
- }
-
- if (_decorations & Client::Decor_Handle) {
- geom.handle_y = _innersize.top + _client->area().height() + geom.cbwidth;
- XMoveResizeWindow(**otk::display, _handle, -geom.bwidth, geom.handle_y,
- geom.width, geom.handle_height);
- XMoveWindow(**otk::display, _lgrip, -geom.bwidth, -geom.bwidth);
- XMoveWindow(**otk::display, _rgrip,
- -geom.bwidth + geom.width - geom.grip_width(),
- -geom.bwidth);
- _innersize.bottom += geom.handle_height + geom.bwidth;
- XMapWindow(**otk::display, _handle);
- } else
- XUnmapWindow(**otk::display, _handle);
-
- XResizeWindow(**otk::display, _frame, geom.width,
- (_client->shaded() ? geom.title_height() :
- _innersize.top + _innersize.bottom +
- _client->area().height()));
-
- // do this in two steps because clients whose gravity is set to
- // 'Static' don't end up getting moved at all with an XMoveResizeWindow
- XMoveWindow(**otk::display, _plate, _innersize.left - geom.cbwidth,
- _innersize.top - geom.cbwidth);
- XResizeWindow(**otk::display, _plate, _client->area().width(),
- _client->area().height());
-
- _size.left = _innersize.left + geom.bwidth;
- _size.right = _innersize.right + geom.bwidth;
- _size.top = _innersize.top + geom.bwidth;
- _size.bottom = _innersize.bottom + geom.bwidth;
-
- _area = otk::Rect(_area.position(), otk::Size(_client->area().width() +
- _size.left + _size.right,
- _client->area().height() +
- _size.top + _size.bottom));
-
- // render all the elements
- int screen = _client->screen();
- bool focus = _client->focused();
- if (_decorations & Client::Decor_Titlebar) {
- render(screen, otk::Size(geom.width, geom.title_height()), _title,
- &_title_sur, *(focus ? style->titlebarFocusBackground() :
- style->titlebarUnfocusBackground()), false);
-
- renderLabel();
- renderMax();
- renderDesk();
- renderIconify();
- renderIcon();
- renderClose();
- }
-
- if (_decorations & Client::Decor_Handle) {
- render(screen, otk::Size(geom.width, geom.handle_height), _handle,
- &_handle_sur, *(focus ? style->handleFocusBackground() :
- style->handleUnfocusBackground()));
- render(screen, otk::Size(geom.grip_width(), geom.handle_height), _lgrip,
- &_grip_sur, *(focus ? style->gripFocusBackground() :
- style->gripUnfocusBackground()));
- if ((focus ? style->gripFocusBackground() :
- style->gripUnfocusBackground())->parentRelative())
- XSetWindowBackgroundPixmap(**otk::display, _rgrip, ParentRelative);
- else {
- XSetWindowBackgroundPixmap(**otk::display, _rgrip, _grip_sur->pixmap());
- }
- XClearWindow(**otk::display, _rgrip);
- }
-
- XSetWindowBorder(**otk::display, _plate,
- focus ? style->clientBorderFocusColor()->pixel() :
- style->clientBorderUnfocusColor()->pixel());
-
- adjustShape();
-}
-
-void Frame::renderLabel()
-{
- const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen());
- const otk::RenderControl *control =
- otk::display->renderControl(_client->screen());
- const otk::Font *font = style->labelFont();
-
- otk::Surface *s = new otk::Surface(_client->screen(),
- otk::Size(geom.label_width,
- geom.label_height()));
- const otk::RenderTexture *tx = (_client->focused() ?
- style->labelFocusBackground() :
- style->labelUnfocusBackground());
- if (tx->parentRelative()) {
- otk::pixel32 *dest = s->pixelData(), *src;
- int w = _title_sur->size().width();
-
- src = _title_sur->pixelData() + w * geom.bevel + geom.title_x;
-
- // get the background under the label
- int xd = s->size().width();
- int yd = s->size().height();
- for (int y = 0; y < yd; ++y, src += w - xd)
- for (int x = 0; x < xd; ++x, ++dest, ++src)
- *dest = *src;
- control->drawImage(*s, 0, 0, 0); // no image but draw the new background
- } else
- control->drawBackground(*s, *tx);
-
- otk::ustring t = _client->title(); // the actual text to draw
- int x = geom.bevel; // x coord for the text
-
- if (x * 2 < geom.label_width) {
- // find a string that will fit inside the area for text
- otk::ustring::size_type text_len = t.size();
- int length;
- int maxsize = geom.label_width - geom.bevel * 2;
-
- do {
- t.resize(text_len);
- length = font->measureString(t);// this returns an unsigned, so check < 0
- if (length < 0) length = maxsize;// if the string's that long just adjust
- } while (length > maxsize && text_len-- > 0);
-
- // justify the text
- switch (style->labelTextJustify()) {
- case otk::RenderStyle::RightBottomJustify:
- x += maxsize - length;
- break;
- case otk::RenderStyle::CenterJustify:
- x += (maxsize - length) / 2;
- break;
- case otk::RenderStyle::LeftTopJustify:
- break;
- }
-
- if (text_len > 0)
- control->drawString(*s, *font, x, 0,
- *(_client->focused() ? style->textFocusColor() :
- style->textUnfocusColor()), t);
- }
-
- XSetWindowBackgroundPixmap(**otk::display, _label, s->pixmap());
- XClearWindow(**otk::display, _label);
- if (_label_sur) delete _label_sur;
- s->freePixelData();
- _label_sur = s;
-}
-
-static void renderButton(int screen, bool focus, bool press, Window win,
- otk::Surface **sur, int butsize,
- const otk::PixmapMask *mask, int xoffset, int yoffset,
- otk::Surface *bgsurface)
-{
- const otk::RenderStyle *style = otk::RenderStyle::style(screen);
- const otk::RenderControl *control = otk::display->renderControl(screen);
- otk::Surface *s = new otk::Surface(screen, otk::Size(butsize, butsize));
-
- const otk::RenderTexture *tx = (focus ?
- (press ?
- style->buttonPressFocusBackground() :
- style->buttonUnpressFocusBackground()) :
- (press ?
- style->buttonPressUnfocusBackground() :
- style->buttonUnpressUnfocusBackground()));
- const otk::RenderColor *maskcolor = (focus ?
- style->buttonFocusColor() :
- style->buttonUnfocusColor());
- if (tx->parentRelative()) {
- otk::pixel32 *dest = s->pixelData(), *src;
- int w = bgsurface->size().width();
-
- src = bgsurface->pixelData() + w * yoffset + xoffset;
-
- // get the background under the button
- for (int y = 0; y < butsize; ++y, src += w - butsize)
- for (int x = 0; x < butsize; ++x, ++dest, ++src)
- *dest = *src;
- control->drawImage(*s, 0, 0, 0); // no image but draw the new background
- } else
- control->drawBackground(*s, *tx);
- control->drawMask(*s, *maskcolor, *mask);
-
- XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap());
- XClearWindow(**otk::display, win);
- if (*sur) delete *sur;
- s->freePixelData();
- *sur = s;
-}
-
-void Frame::renderMax()
-{
- if (!(_decorations & Client::Decor_Maximize)) return;
- bool press = _max_press || _client->maxVert() || _client->maxHorz();
- renderButton(_client->screen(), _client->focused(), press, _max,
- &_max_sur, geom.button_size,
- otk::RenderStyle::style(_client->screen())->maximizeMask(),
- geom.max_x, (geom.bevel + 1), _title_sur);
-}
-
-void Frame::renderDesk()
-{
- if (!(_decorations & Client::Decor_AllDesktops)) return;
- bool press = _desk_press || _client->desktop() == 0xffffffff;
- renderButton(_client->screen(), _client->focused(), press, _desk,
- &_desk_sur, geom.button_size,
- otk::RenderStyle::style(_client->screen())->alldesktopsMask(),
- geom.desktop_x, (geom.bevel + 1), _title_sur);
-}
-
-void Frame::renderIconify()
-{
- if (!(_decorations & Client::Decor_Iconify)) return;
- renderButton(_client->screen(), _client->focused(), _iconify_press, _iconify,
- &_iconify_sur, geom.button_size,
- otk::RenderStyle::style(_client->screen())->iconifyMask(),
- geom.iconify_x, (geom.bevel + 1), _title_sur);
-}
-
-void Frame::renderClose()
-{
- if (!(_decorations & Client::Decor_Close)) return;
- renderButton(_client->screen(), _client->focused(), _close_press, _close,
- &_close_sur, geom.button_size,
- otk::RenderStyle::style(_client->screen())->closeMask(),
- geom.close_x, (geom.bevel + 1), _title_sur);
-}
-
-void Frame::renderIcon()
-{
- if (!(_decorations & Client::Decor_Icon)) return;
- const int screen = _client->screen();
- const otk::RenderControl *control = otk::display->renderControl(screen);
-
- otk::Surface *s = new otk::Surface(screen, otk::Size(geom.button_size,
- geom.button_size));
- otk::pixel32 *dest = s->pixelData(), *src;
- int w = _title_sur->size().width();
-
- src = _title_sur->pixelData() + w * (geom.bevel + 1) + geom.icon_x;
-
- // get the background under the icon button
- for (int y = 0; y < geom.button_size; ++y, src += w - geom.button_size)
- for (int x = 0; x < geom.button_size; ++x, ++dest, ++src)
- *dest = *src;
- // draw the icon over it
- const Icon *icon = _client->icon(otk::Size(geom.button_size,
- geom.button_size));
- control->drawImage(*s, icon->w, icon->h, icon->data);
- if (!icon->data) {
- Pixmap p = _client->pixmapIcon(), m = _client->pixmapIconMask();
- if (p != None)
- control->drawImage(*s, p, m);
- }
-
- XSetWindowBackgroundPixmap(**otk::display, _icon, s->pixmap());
- XClearWindow(**otk::display, _icon);
- if (_icon_sur) delete _icon_sur;
- _icon_sur = s;
-}
-
-void Frame::layoutTitle()
-{
- // figure out whats being shown, and the width of the label
- geom.label_width = geom.width - geom.bevel * 2;
- bool n, d, i, t, m ,c;
- n = d = i = t = m = c = false;
- for (const char *l = _layout.c_str(); *l; ++l) {
- switch (*l) {
- case 'n':
- case 'N':
- if (!(_decorations & Client::Decor_Icon)) break;
- n = true;
- geom.label_width -= geom.button_size + geom.bevel;
- break;
- case 'd':
- case 'D':
- if (!(_decorations & Client::Decor_AllDesktops)) break;
- d = true;
- geom.label_width -= geom.button_size + geom.bevel;
- break;
- case 'i':
- case 'I':
- if (!(_decorations & Client::Decor_Iconify)) break;
- i = true;
- geom.label_width -= geom.button_size + geom.bevel;
- break;
- case 't':
- case 'T':
- t = true;
- break;
- case 'm':
- case 'M':
- if (!(_decorations & Client::Decor_Maximize)) break;
- m = true;
- geom.label_width -= geom.button_size + geom.bevel;
- break;
- case 'c':
- case 'C':
- if (!(_decorations & Client::Decor_Close)) break;
- c = true;
- geom.label_width -= geom.button_size + geom.bevel;
- break;
- }
- }
- if (geom.label_width < 1) geom.label_width = 1;
-
- XResizeWindow(**otk::display, _label, geom.label_width, geom.font_height);
-
- if (!n) {
- _decorations &= ~Client::Decor_Icon;
- XUnmapWindow(**otk::display, _icon);
- }
- if (!d) {
- _decorations &= ~Client::Decor_AllDesktops;
- XUnmapWindow(**otk::display, _desk);
- }
- if (!i) {
- _decorations &= ~Client::Decor_Iconify;
- XUnmapWindow(**otk::display, _iconify);
- }
- if (!t)
- XUnmapWindow(**otk::display, _label);
- if (!m) {
- _decorations &= ~Client::Decor_Maximize;
- XUnmapWindow(**otk::display, _max);
- }
- if (!c) {
- _decorations &= ~Client::Decor_Close;
- XUnmapWindow(**otk::display, _close);
- }
-
- int x = geom.bevel;
- for (const char *lc = _layout.c_str(); *lc; ++lc) {
- switch (*lc) {
- case 'n':
- case 'N':
- if (!n) break;
- geom.icon_x = x;
- XMapWindow(**otk::display, _icon);
- XMoveWindow(**otk::display, _icon, x, geom.bevel + 1);
- x += geom.button_size + geom.bevel;
- break;
- case 'd':
- case 'D':
- if (!d) break;
- geom.desktop_x = x;
- XMapWindow(**otk::display, _desk);
- XMoveWindow(**otk::display, _desk, x, geom.bevel + 1);
- x += geom.button_size + geom.bevel;
- break;
- case 'i':
- case 'I':
- if (!i) break;
- geom.iconify_x = x;
- XMapWindow(**otk::display, _iconify);
- XMoveWindow(**otk::display, _iconify, x, geom.bevel + 1);
- x += geom.button_size + geom.bevel;
- break;
- case 't':
- case 'T':
- if (!t) break;
- geom.title_x = x;
- XMapWindow(**otk::display, _label);
- XMoveWindow(**otk::display, _label, x, geom.bevel);
- x += geom.label_width + geom.bevel;
- break;
- case 'm':
- case 'M':
- if (!m) break;
- geom.max_x = x;
- XMapWindow(**otk::display, _max);
- XMoveWindow(**otk::display, _max, x, geom.bevel + 1);
- x += geom.button_size + geom.bevel;
- break;
- case 'c':
- case 'C':
- if (!c) break;
- geom.close_x = x;
- XMapWindow(**otk::display, _close);
- XMoveWindow(**otk::display, _close, x, geom.bevel + 1);
- x += geom.button_size + geom.bevel;
- break;
- }
- }
-}
-
-void Frame::adjustPosition()
-{
- int x, y;
- x = _client->area().x();
- y = _client->area().y();
- clientGravity(x, y);
- XMoveWindow(**otk::display, _frame, x, y);
- _area = otk::Rect(otk::Point(x, y), _area.size());
-}
-
-
-void Frame::adjustShape()
-{
-#ifdef SHAPE
- if (!_client->shaped()) {
- // clear the shape on the frame window
- XShapeCombineMask(**otk::display, _frame, ShapeBounding,
- _innersize.left,
- _innersize.top,
- None, ShapeSet);
- } else {
- // make the frame's shape match the clients
- XShapeCombineShape(**otk::display, _frame, ShapeBounding,
- _innersize.left,
- _innersize.top,
- _client->window(), ShapeBounding, ShapeSet);
-
- int num = 0;
- XRectangle xrect[2];
-
- if (_decorations & Client::Decor_Titlebar) {
- xrect[0].x = -geom.bevel;
- xrect[0].y = -geom.bevel;
- xrect[0].width = geom.width + geom.bwidth * 2;
- xrect[0].height = geom.title_height() + geom.bwidth * 2;
- ++num;
- }
-
- if (_decorations & Client::Decor_Handle) {
- xrect[1].x = -geom.bevel;
- xrect[1].y = geom.handle_y;
- xrect[1].width = geom.width + geom.bwidth * 2;
- xrect[1].height = geom.handle_height + geom.bwidth * 2;
- ++num;
- }
-
- XShapeCombineRectangles(**otk::display, _frame,
- ShapeBounding, 0, 0, xrect, num,
- ShapeUnion, Unsorted);
- }
-#endif // SHAPE
-}
-
-void Frame::adjustState()
-{
- renderDesk();
- renderMax();
-}
-
-void Frame::adjustIcon()
-{
- renderIcon();
-}
-
-void Frame::grabClient()
-{
- // reparent the client to the frame
- XReparentWindow(**otk::display, _client->window(), _plate, 0, 0);
- /*
- When reparenting the client window, it is usually not mapped yet, since
- this occurs from a MapRequest. However, in the case where Openbox is
- starting up, the window is already mapped, so we'll see unmap events for
- it. There are 2 unmap events generated that we see, one with the 'event'
- member set the root window, and one set to the client, but both get handled
- and need to be ignored.
- */
- if (openbox->state() == Openbox::State_Starting)
- _client->ignore_unmaps += 2;
-
- // select the event mask on the client's parent (to receive config/map req's)
- // the ButtonPress is to catch clicks on the client border
- XSelectInput(**otk::display, _plate, (SubstructureRedirectMask |
- ButtonPressMask));
-
- // map the client so it maps when the frame does
- XMapWindow(**otk::display, _client->window());
-
- adjustSize();
- adjustPosition();
-}
-
-
-void Frame::releaseClient()
-{
- XEvent ev;
-
- // check if the app has already reparented its window away
- if (XCheckTypedWindowEvent(**otk::display, _client->window(),
- ReparentNotify, &ev)) {
- XPutBackEvent(**otk::display, &ev);
- // re-map the window since the unmanaging process unmaps it
- XMapWindow(**otk::display, _client->window());
- } else {
- // according to the ICCCM - if the client doesn't reparent itself, then we
- // will reparent the window to root for them
- XReparentWindow(**otk::display, _client->window(),
- otk::display->screenInfo(_client->screen())->rootWindow(),
- _client->area().x(), _client->area().y());
- }
-}
-
-
-void Frame::clientGravity(int &x, int &y)
-{
- // horizontal
- switch (_client->gravity()) {
- default:
- case NorthWestGravity:
- case SouthWestGravity:
- case WestGravity:
- break;
-
- case NorthGravity:
- case SouthGravity:
- case CenterGravity:
- x -= (_size.left + _size.right) / 2;
- break;
-
- case NorthEastGravity:
- case SouthEastGravity:
- case EastGravity:
- x -= _size.left + _size.right;
- break;
-
- case ForgetGravity:
- case StaticGravity:
- x -= _size.left;
- break;
- }
-
- // vertical
- switch (_client->gravity()) {
- default:
- case NorthWestGravity:
- case NorthEastGravity:
- case NorthGravity:
- break;
-
- case CenterGravity:
- case EastGravity:
- case WestGravity:
- y -= (_size.top + _size.bottom) / 2;
- break;
-
- case SouthWestGravity:
- case SouthEastGravity:
- case SouthGravity:
- y -= _size.top + _size.bottom;
- break;
-
- case ForgetGravity:
- case StaticGravity:
- y -= _size.top;
- break;
- }
-}
-
-
-void Frame::frameGravity(int &x, int &y)
-{
- // horizontal
- switch (_client->gravity()) {
- default:
- case NorthWestGravity:
- case WestGravity:
- case SouthWestGravity:
- break;
- case NorthGravity:
- case CenterGravity:
- case SouthGravity:
- x += (_size.left + _size.right) / 2;
- break;
- case NorthEastGravity:
- case EastGravity:
- case SouthEastGravity:
- x += _size.left + _size.right;
- break;
- case StaticGravity:
- case ForgetGravity:
- x += _size.left;
- break;
- }
-
- // vertical
- switch (_client->gravity()) {
- default:
- case NorthWestGravity:
- case WestGravity:
- case SouthWestGravity:
- break;
- case NorthGravity:
- case CenterGravity:
- case SouthGravity:
- y += (_size.top + _size.bottom) / 2;
- break;
- case NorthEastGravity:
- case EastGravity:
- case SouthEastGravity:
- y += _size.top + _size.bottom;
- break;
- case StaticGravity:
- case ForgetGravity:
- y += _size.top;
- break;
- }
-}
-
-
-}
diff --git a/src/frame.hh b/src/frame.hh
deleted file mode 100644
index 7fa7a513..00000000
--- a/src/frame.hh
+++ /dev/null
@@ -1,203 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef __frame_hh
-#define __frame_hh
-
-/*! @file frame.hh
-*/
-
-extern "C" {
-#include <X11/Xlib.h>
-}
-
-#include "client.hh"
-#include "python.hh"
-#include "otk/strut.hh"
-#include "otk/rect.hh"
-#include "otk/renderstyle.hh"
-#include "otk/ustring.hh"
-#include "otk/surface.hh"
-#include "otk/eventhandler.hh"
-
-#include <string>
-#include <vector>
-
-namespace ob {
-
-//! Varius geometry settings in the frame decorations
-struct FrameGeometry {
- int width; // title and handle
- int font_height;
- int title_height() { return font_height + bevel*2; }
- int label_width;
- int label_height() { return font_height; }
- int handle_height; // static, from the style
- int icon_x; // x-position of the window icon button
- int title_x; // x-position of the window title
- int iconify_x; // x-position of the window iconify button
- int desktop_x; // x-position of the window all-desktops button
- int max_x; // x-position of the window maximize button
- int close_x; // x-position of the window close button
- int handle_y;
- int button_size; // static, from the style
- int grip_width() { return button_size * 2; }
- int bevel; // static, from the style
- int bwidth; // frame elements' border width
- int cbwidth; // client border width
-};
-
-//! Holds and decorates a frame around an Client (client window)
-/*!
- The frame is responsible for calling XSelectInput on the client window's new
- parent with the SubstructureRedirectMask so that structure events for the
- client are sent to the window manager.
-*/
-class Frame : public otk::StyleNotify, public otk::EventHandler {
-public:
-
- //! The event mask to grab on frame windows
- static const long event_mask = EnterWindowMask | LeaveWindowMask;
-
-private:
- Client *_client;
-
- //! The size of the frame on each side of the client window
- otk::Strut _size;
-
- //! The size of the frame on each side of the client window inside the border
- otk::Strut _innersize;
-
- //! The position and size of the entire frame (including borders)
- otk::Rect _area;
-
- bool _visible;
-
- //! The decorations that are being displayed in the frame.
- Client::DecorationFlags _decorations;
-
- // decoration windows
- Window _frame; // sits under everything
- Window _plate; // sits entirely under the client window
- Window _title; // the titlebar
- Window _label; // the section of the titlebar which shows the window name
- Window _handle; // bottom bar
- Window _lgrip; // lefthand resize grab on the handle
- Window _rgrip; // righthand resize grab on the handle
- Window _max; // maximize button
- Window _desk; // all-desktops button
- Window _iconify; // iconify button
- Window _icon; // window icon button
- Window _close; // close button
-
- // surfaces for each
- otk::Surface *_frame_sur;
- otk::Surface *_title_sur;
- otk::Surface *_label_sur;
- otk::Surface *_handle_sur;
- otk::Surface *_grip_sur;
- otk::Surface *_max_sur;
- otk::Surface *_desk_sur;
- otk::Surface *_iconify_sur;
- otk::Surface *_icon_sur;
- otk::Surface *_close_sur;
-
- otk::ustring _layout; // layout of the titlebar
-
- bool _max_press;
- bool _desk_press;
- bool _iconify_press;
- bool _icon_press;
- bool _close_press;
- unsigned int _press_button; // mouse button that started the press
-
- FrameGeometry geom;
-
- void applyStyle(const otk::RenderStyle &style);
- void layoutTitle();
- void renderLabel();
- void renderMax();
- void renderDesk();
- void renderIconify();
- void renderClose();
- void renderIcon();
-
-public:
- //! Constructs an Frame object for a client
- /*!
- @param client The client which will be decorated by the new Frame
- */
- Frame(Client *client);
- //! Destroys the Frame object
- virtual ~Frame();
-
- //! Returns the size of the frame on each side of the client
- const otk::Strut& size() const { return _size; }
-
- //! Set the style to decorate the frame with
- virtual void styleChanged(const otk::RenderStyle &style);
-
- //! Reparents the client window from the root window onto the frame
- void grabClient();
- //! Reparents the client window back to the root window
- void releaseClient();
-
- //! Update the frame's size to match the client
- void adjustSize();
- //! Update the frame's position to match the client
- void adjustPosition();
- //! Shape the frame window to the client window
- void adjustShape();
- //! Update the frame to match the client's new state (for things like toggle
- //! buttons, focus, and the title) XXX break this up
- void adjustState();
- void adjustFocus();
- void adjustTitle();
- void adjustIcon();
-
- //! Applies gravity to the client's position to find where the frame should
- //! be positioned.
- /*!
- @return The proper coordinates for the frame, based on the client.
- */
- void clientGravity(int &x, int &y);
-
- //! Reversly applies gravity to the frame's position to find where the client
- //! should be positioned.
- /*!
- @return The proper coordinates for the client, based on the frame.
- */
- void frameGravity(int &x, int &y);
-
- //! The position and size of the frame window
- inline const otk::Rect& area() const { return _area; }
-
- //! Returns if the frame is visible
- inline bool visible() const { return _visible; }
-
- //! Shows the frame
- void show();
- //! Hides the frame
- void hide();
-
- void buttonPressHandler(const XButtonEvent &e);
- void buttonReleaseHandler(const XButtonEvent &e);
-
- //! Returns the MouseContext for the given window id
- /*!
- Returns '-1' if no valid mouse context exists in the frame for the given
- id.
- */
- ob::MouseContext::MC mouseContext(Window win) const;
-
- //! Gets the window id of the frame's base top-level parent
- inline Window window() const { return _frame; }
- //! Gets the window id of the client's parent window
- inline Window plate() const { return _plate; }
-
- //! Returns a null terminated array of the window ids that make up the
- //! frame's decorations.
- Window *allWindows() const;
-};
-
-}
-
-#endif // __frame_hh
diff --git a/src/gettext.h b/src/gettext.h
deleted file mode 100644
index 6de66d23..00000000
--- a/src/gettext.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Convenience header for conditional use of GNU <libintl.h>.
- Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
-
-#ifndef _LIBGETTEXT_H
-#define _LIBGETTEXT_H 1
-
-
-/* NLS can be disabled through the configure --disable-nls option. */
-#if ENABLE_NLS
-
-/* Get declarations of GNU message catalog functions. */
-# include <libintl.h>
-
-#else
-
-/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
- chokes if dcgettext is defined as a macro. So include it now, to make
- later inclusions of <locale.h> a NOP. We don't include <libintl.h>
- as well because people using "gettext.h" will not include <libintl.h>,
- and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
- is OK. */
-#if defined(__sun)
-# include <locale.h>
-#endif
-
-/* Disabled NLS.
- The casts to 'const char *' serve the purpose of producing warnings
- for invalid uses of the value returned from these functions.
- On pre-ANSI systems without 'const', the config.h file is supposed to
- contain "#define const". */
-# define gettext(Msgid) ((const char *) (Msgid))
-# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
-# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
-# define ngettext(Msgid1, Msgid2, N) \
- ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
-# define dngettext(Domainname, Msgid1, Msgid2, N) \
- ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
-# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
- ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
-# define textdomain(Domainname) ((const char *) (Domainname))
-# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
-# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
-
-#endif
-
-/* A pseudo function call that serves as a marker for the automated
- extraction of messages, but does not call gettext(). The run-time
- translation is done at a different place in the code.
- The argument, String, should be a literal string. Concatenated strings
- and other string expressions won't work.
- The macro's expansion is not parenthesized, so that it is suitable as
- initializer for static 'char[]' or 'const char[]' variables. */
-#define gettext_noop(String) String
-
-#endif /* _LIBGETTEXT_H */
diff --git a/src/main.cc b/src/main.cc
deleted file mode 100644
index 13047780..00000000
--- a/src/main.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-/*! @file main.cc
- @brief Main entry point for the application
-*/
-
-#include "config.h"
-
-extern "C" {
-#ifdef HAVE_UNISTD_H
-# include <sys/types.h>
-# include <unistd.h>
-#endif // HAVE_UNISTD_H
-
-#include "gettext.h"
-}
-
-#include "openbox.hh"
-#include "otk/util.hh"
-
-#include <clocale>
-#include <cstdio>
-
-int main(int argc, char **argv) {
- // initialize the locale
- if (!setlocale(LC_ALL, ""))
- printf("Couldn't set locale from environment.\n");
- bindtextdomain(PACKAGE, LOCALEDIR);
- bind_textdomain_codeset(PACKAGE, "UTF-8");
- textdomain(PACKAGE);
-
- ob::Openbox *openbox = new ob::Openbox(argc, argv);
- openbox->eventLoop();
-
- if (openbox->doRestart()) {
- std::string prog = openbox->restartProgram();
-
- delete openbox; // shutdown the current one!
-
- if (!prog.empty()) {
- execl("/bin/sh", "/bin/sh", "-c", prog.c_str(), NULL);
- perror(prog.c_str());
- }
-
- // fall back in case the above execlp doesn't work
- execvp(argv[0], argv);
- execvp(otk::basename(argv[0]).c_str(), argv);
- }
-
- delete openbox; // shutdown
-}
diff --git a/src/openbox.cc b/src/openbox.cc
deleted file mode 100644
index d2ce85fd..00000000
--- a/src/openbox.cc
+++ /dev/null
@@ -1,413 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#include "config.h"
-
-#include "openbox.hh"
-#include "client.hh"
-#include "screen.hh"
-#include "actions.hh"
-#include "bindings.hh"
-#include "python.hh"
-#include "otk/property.hh"
-#include "otk/assassin.hh"
-#include "otk/property.hh"
-#include "otk/util.hh"
-#include "otk/rendercolor.hh"
-#include "otk/renderstyle.hh"
-#include "otk/messagedialog.hh"
-
-extern "C" {
-#include <X11/cursorfont.h>
-
-#ifdef HAVE_SIGNAL_H
-# include <signal.h>
-#endif // HAVE_SIGNAL_H
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif // HAVE_FCNTL_H
-
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif // HAVE_SYS_WAIT_H
-
-#include "gettext.h"
-#define _(str) gettext(str)
-}
-
-#include <algorithm>
-#include <cstdio>
-#include <cstdlib>
-
-namespace otk {
-extern void initialize();
-extern void destroy();
-}
-
-namespace ob {
-
-Openbox *openbox = (Openbox *) 0;
-
-
-void Openbox::signalHandler(int signal)
-{
- switch (signal) {
- case SIGUSR1:
- printf("Caught SIGUSR1 signal. Restarting.\n");
- openbox->restart();
- break;
-
- case SIGCHLD:
- wait(NULL);
- break;
-
- case SIGHUP:
- case SIGINT:
- case SIGTERM:
- case SIGPIPE:
- printf("Caught signal %d. Exiting.\n", signal);
- openbox->shutdown();
- break;
-
- case SIGFPE:
- case SIGSEGV:
- printf("Caught signal %d. Aborting and dumping core.\n", signal);
- abort();
- }
-}
-
-
-Openbox::Openbox(int argc, char **argv)
- : otk::EventDispatcher(),
- otk::EventHandler()
-{
- struct sigaction action;
-
- _state = State_Starting; // initializing everything
-
- openbox = this;
-
- _argv = argv;
- _shutdown = false;
- _restart = false;
- _rcfilepath = otk::expandTilde("~/.openbox/rc3");
- _scriptfilepath = otk::expandTilde("~/.openbox/user.py");
- _focused_client = 0;
- _sync = false;
- _single = false;
- _remote = false;
-
- parseCommandLine(argc, argv);
-
- otk::initialize();
-
- XSynchronize(**otk::display, _sync);
-
- // set up the signal handler
- action.sa_handler = Openbox::signalHandler;
- action.sa_mask = sigset_t();
- action.sa_flags = SA_NOCLDSTOP | SA_NODEFER;
- sigaction(SIGUSR1, &action, (struct sigaction *) 0);
- sigaction(SIGPIPE, &action, (struct sigaction *) 0);
- sigaction(SIGSEGV, &action, (struct sigaction *) 0);
- sigaction(SIGFPE, &action, (struct sigaction *) 0);
- sigaction(SIGTERM, &action, (struct sigaction *) 0);
- sigaction(SIGINT, &action, (struct sigaction *) 0);
- sigaction(SIGHUP, &action, (struct sigaction *) 0);
- sigaction(SIGCHLD, &action, (struct sigaction *) 0);
-
- // anything that died while we were restarting won't give us a SIGCHLD
- while (waitpid(-1, NULL, WNOHANG) > 0);
-
- _actions = new Actions();
- _bindings = new Bindings();
-
- setMasterHandler(_actions); // set as the master event handler
-
- // create the mouse cursors we'll use
- _cursors.session = XCreateFontCursor(**otk::display, XC_left_ptr);
- _cursors.move = XCreateFontCursor(**otk::display, XC_fleur);
- _cursors.ll_angle = XCreateFontCursor(**otk::display, XC_ll_angle);
- _cursors.lr_angle = XCreateFontCursor(**otk::display, XC_lr_angle);
- _cursors.ul_angle = XCreateFontCursor(**otk::display, XC_ul_angle);
- _cursors.ur_angle = XCreateFontCursor(**otk::display, XC_ur_angle);
-
- // initialize all the screens
- _focused_screen = 0;
- _managed_count = 0;
-
- for (int i = 0, max = ScreenCount(**otk::display); i < max; ++i) {
- Screen *screen;
- // in single mode skip the screens we don't want to manage
- if (_single && i != DefaultScreen(**otk::display)) {
- _screens.push_back(0);
- continue;
- }
- // try manage the screen
- screen = new Screen(i);
- if (screen->managed()) {
- _screens.push_back(screen);
- if (!_focused_screen) // set this to the first screen managed
- _focused_screen = screen;
- _managed_count++;
- } else {
- delete screen;
- _screens.push_back(0);
- }
- }
-
- if (!_managed_count) {
- printf(_("No screens were found without a window manager. Exiting.\n"));
- ::exit(1);
- }
-
- assert(_focused_screen);
-
- // initialize scripting
- python_init(argv[0]);
-
- // load the theme XXX TEMP SHIT
- otk::RenderStyle::setStyle(0, "");
-
- int ret = python_exec(_scriptfilepath.c_str());
- if (ret == 2) {
- std::string msg;
- msg += _("An error occured while executing the python scripts.");
- msg += "\n\n";
- msg += _("See the exact error message in Openbox's output for details.");
- otk::MessageDialog dia(this, _("Python Error"), msg);
- otk::DialogButton ok(_("Okay"), true);
- otk::DialogButton retry(_("Restart"));
- dia.addButton(ok);
- dia.addButton(retry);
- dia.show();
- dia.focus();
- const otk::DialogButton &res = dia.run();
- if (res == retry) {
- _restart = _shutdown = true;
- return;
- }
- }
-
- if (ret)
- python_exec(SCRIPTDIR"/defaults.py"); // system default bahaviors
-
- ScreenList::iterator it, end = _screens.end();
- for (it = _screens.begin(); it != end; ++it)
- if (*it) (*it)->manageExisting();
-
- // grab any keys set up before the screens existed
- //_bindings->grabKeys(true);
-
- // set up input focus
- setFocusedClient(0);
-
- _state = State_Normal; // done starting
-}
-
-
-Openbox::~Openbox()
-{
- _state = State_Exiting; // time to kill everything
-
- std::for_each(_screens.begin(), _screens.end(), otk::PointerAssassin());
-
- delete _bindings;
- delete _actions;
-
- python_destroy();
-
- XSetInputFocus(**otk::display, PointerRoot, RevertToNone,
- CurrentTime);
- XSync(**otk::display, false);
-
- otk::destroy();
-}
-
-
-void Openbox::parseCommandLine(int argc, char **argv)
-{
- bool err = false;
-
- for (int i = 1; i < argc; ++i) {
- std::string arg(argv[i]);
-
- if (arg == "-rc") {
- if (++i >= argc)
- err = true;
- else
- _rcfilepath = argv[i];
- } else if (arg == "-menu") {
- if (++i >= argc)
- err = true;
- else
- _menufilepath = argv[i];
- } else if (arg == "-script") {
- if (++i >= argc)
- err = true;
- else
- _scriptfilepath = argv[i];
- } else if (arg == "-sync") {
- _sync = true;
- } else if (arg == "-single") {
- _single = true;
- } else if (arg == "-remote") {
- _remote = true;
- } else if (arg == "-version") {
- showVersion();
- ::exit(0);
- } else if (arg == "-help") {
- showHelp();
- ::exit(0);
- } else
- err = true;
-
- if (err) {
- showHelp();
- exit(1);
- }
- }
-}
-
-
-void Openbox::showVersion()
-{
- printf(_("Openbox - version %s\n"), VERSION);
- printf(" (c) 2002 - 2002 Ben Jansens\n\n");
-}
-
-
-void Openbox::showHelp()
-{
- showVersion(); // show the version string and copyright
-
- // print program usage and command line options
- printf(_("Usage: %s [OPTIONS...]\n\
- Options:\n\
- -remote optimize for a remote (low bandwidth) connection to the\n\
- display/Xserver.\n\
- -single run on a single screen (default is to run every one).\n\
- -rc <string> use alternate resource file.\n\
- -menu <string> use alternate menu file.\n\
- -script <string> use alternate startup script file.\n\
- -sync run in synchronous mode (for debugging X errors).\n\
- -version display version and exit.\n\
- -help display this help text and exit.\n\n"), _argv[0]);
-
- printf(_("Compile time options:\n\
- Debugging: %s\n\
- Shape: %s\n\
- Xinerama: %s\n\
- Xkb: %s\n"),
-#ifdef DEBUG
- _("yes"),
-#else // !DEBUG
- _("no"),
-#endif // DEBUG
-
-#ifdef SHAPE
- _("yes"),
-#else // !SHAPE
- _("no"),
-#endif // SHAPE
-
-#ifdef XINERAMA
- _("yes"),
-#else // !XINERAMA
- _("no"),
-#endif // XINERAMA
-
-#ifdef XKB
- _("yes")
-#else // !XKB
- _("no")
-#endif // XKB
- );
-}
-
-
-void Openbox::eventLoop()
-{
- while (true) {
- dispatchEvents(false); // from otk::EventDispatcher
-// XFlush(**otk::display); // flush here before we go wait for timers
- // .. the XPending() should have done this last
- // already, it does a flush when it returns 0
- // don't wait if we're to shutdown
- if (_shutdown) break;
- otk::Timer::dispatchTimers(!_sync); // wait if not in sync mode
- }
-}
-
-
-void Openbox::addClient(Window window, Client *client)
-{
- _clients[window] = client;
-}
-
-
-void Openbox::removeClient(Window window)
-{
- _clients.erase(window);
-}
-
-
-Client *Openbox::findClient(Window window)
-{
- /*
- NOTE: we dont use _clients[] to find the value because that will insert
- a new null into the hash, which really sucks when we want to clean up the
- hash at shutdown!
- */
- ClientMap::iterator it = _clients.find(window);
- if (it != _clients.end())
- return it->second;
- else
- return (Client*) 0;
-}
-
-
-void Openbox::setFocusedClient(Client *c)
-{
- // sometimes this is called with the already-focused window, this is
- // important for the python scripts to work (eg, c = 0 twice). don't just
- // return if _focused_client == c
-
- assert(_focused_screen);
-
- // uninstall the old colormap
- if (_focused_client)
- _focused_client->installColormap(false);
- else
- _focused_screen->installColormap(false);
-
- _focused_client = c;
- if (c) {
- _focused_screen = _screens[c->screen()];
-
- // install the client's colormap
- c->installColormap(true);
- } else {
- XSetInputFocus(**otk::display, _focused_screen->focuswindow(),
- RevertToNone, CurrentTime);
-
- // install the root window colormap
- _focused_screen->installColormap(true);
- }
- // set the NET_ACTIVE_WINDOW hint for all screens
- ScreenList::iterator it, end = _screens.end();
- for (it = _screens.begin(); it != end; ++it) {
- int num = (*it)->number();
- Window root = otk::display->screenInfo(num)->rootWindow();
- otk::Property::set(root, otk::Property::atoms.net_active_window,
- otk::Property::atoms.window,
- (c && _focused_screen == *it) ? c->window() : None);
- }
-
- // call the python Focus callbacks
- EventData data(_focused_screen->number(), c, EventAction::Focus, 0);
- _bindings->fireEvent(&data);
-}
-
-}
-
diff --git a/src/openbox.hh b/src/openbox.hh
deleted file mode 100644
index 460caa0c..00000000
--- a/src/openbox.hh
+++ /dev/null
@@ -1,250 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef __openbox_hh
-#define __openbox_hh
-
-/*! @file openbox.hh
- @brief The main class for the Openbox window manager
-*/
-
-extern "C" {
-#include <X11/Xlib.h>
-}
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "otk/display.hh"
-#include "otk/screeninfo.hh"
-#include "otk/eventdispatcher.hh"
-#include "otk/eventhandler.hh"
-
-namespace ob {
-
-class Screen;
-class Client;
-class Actions;
-class Bindings;
-
-//! Mouse cursors used throughout Openbox
-struct Cursors {
- Cursor session; //!< The default mouse cursor
- Cursor move; //!< For moving a window
- Cursor ll_angle; //!< For resizing the bottom left corner of a window
- Cursor lr_angle; //!< For resizing the bottom right corner of a window
- Cursor ul_angle; //!< For resizing the top left corner of a window
- Cursor ur_angle; //!< For resizing the right corner of a window
-};
-
-class Openbox;
-
-//! The single instance of the Openbox class for the application
-/*!
- Since this variable is globally available in the application, the Openbox
- class does not need to be passed around to any of the other classes.
-*/
-extern Openbox *openbox;
-
-//! The main class for the Openbox window manager
-/*!
- Only a single instance of the Openbox class may be used in the application. A
- pointer to this instance is held in the Openbox::instance static member
- variable.
- Instantiation of this class begins the window manager. After instantiation,
- the Openbox::eventLoop function should be called. The eventLoop method does
- not exit until the window manager is ready to be destroyed. Destruction of
- the Openbox class instance will shutdown the window manager.
-*/
-class Openbox : public otk::EventDispatcher, public otk::EventHandler
-{
-public:
- //! The posible running states of the window manager
- enum RunState {
- State_Starting, //!< The window manager is starting up (being created)
- State_Normal, //!< The window manager is running in its normal state
- State_Exiting //!< The window manager is exiting (being destroyed)
- };
-
- //! A map for looking up a specific client class from the window id
- typedef std::map<Window, Client *> ClientMap;
-
- //! A list of Screen classes
- typedef std::vector<Screen *> ScreenList;
-
-private:
- // stuff that can be passed on the command line
- //! Path to the config file to use/in use
- /*!
- Defaults to $(HOME)/.openbox/rc3
- */
- std::string _rcfilepath;
- //! Path to the menu file to use/in use
- /*!
- Defaults to $(HOME)/.openbox/menu3
- */
- std::string _menufilepath;
- //! Path to the script file to execute on startup
- /*!
- Defaults to $(HOME)/.openbox/user.py
- */
- std::string _scriptfilepath;
- //! The value of argv, i.e. how this application was executed
- char **_argv;
- //! Run the application in synchronous mode? (for debugging)
- bool _sync;
- //! Should Openbox run on a single screen or on all available screens?
- bool _single;
- //! Optimize for a remote/low-bandwidth connection to the display?
- bool _remote;
-
- //! A list of all managed clients
- ClientMap _clients;
-
- //! A list of all the managed screens
- ScreenList _screens;
-
- //! The number of managed screens
- int _managed_count;
-
- //! The action interface through which all user-available actions occur
- Actions *_actions;
-
- //! The interface through which keys/buttons are grabbed and handled
- Bindings *_bindings;
-
- //! The running state of the window manager
- RunState _state;
-
- //! Mouse cursors used throughout Openbox
- Cursors _cursors;
-
- //! When set to true, the Openbox::eventLoop function will stop and return
- bool _shutdown;
-
- //! When set to true, and Openbox is about to exit, it will spawn a new
- //! process
- bool _restart;
-
- //! If this contains anything, a restart will try to execute the program in
- //! this variable, and will fallback to reexec'ing itself if that fails
- std::string _restart_prog;
-
- //! The client with input focus
- /*!
- Updated by the clients themselves.
- */
- Client *_focused_client;
-
- //! The screen with input focus
- /*!
- Updated by the clients when they update the Openbox::focused_client
- property.
- */
- Screen *_focused_screen;
-
- //! Parses the command line used when executing this application
- void parseCommandLine(int argv, char **argv);
- //! Displays the version string to stdout
- void showVersion();
- //! Displays usage information and help to stdout
- void showHelp();
-
- //! Handles signal events for the application
- static void signalHandler(int signal);
-
-public:
- //! Openbox constructor.
- /*!
- \param argc Number of command line arguments, as received in main()
- \param argv The command line arguments, as received in main()
- */
- Openbox(int argc, char **argv);
- //! Openbox destructor.
- virtual ~Openbox();
-
- //! Returns the state of the window manager (starting, exiting, etc)
- inline RunState state() const { return _state; }
-
- //! Returns the Actions instance for the window manager
- inline Actions *actions() const { return _actions; }
-
- //! Returns the Bindings instance for the window manager
- inline Bindings *bindings() const { return _bindings; }
-
- //! Returns a managed screen or a null pointer
- /*!
- ALWAYS check the return value for a non-null, as any unmanaged screens
- will return one. This includes screen(0) if the first managed screen is 1.
- */
- inline Screen *screen(int num) {
- assert(num >= 0); assert(num < (signed)ScreenCount(**otk::display));
- if (num < 0 || num >= (signed)_screens.size()) return 0;
- return _screens[num];
- }
-
- inline int managedScreenCount() const { return _managed_count; }
-
- inline Screen *managedScreen(int num) {
- assert(num >= 0); assert(num < _managed_count);
- if (num < 0 || num >= _managed_count) return 0;
- ScreenList::iterator it, end = _screens.end();
- int i = -1;
- for (it = _screens.begin(); it != end; ++it)
- if (*it && ++i == num)
- return *it;
- }
-
- //! Returns the mouse cursors used throughout Openbox
- inline const Cursors &cursors() const { return _cursors; }
-
- //! The main function of the Openbox class
- /*!
- This function should be called after instantiating the Openbox class.
- It loops indefinately while handling all events for the application.
- The Openbox::shutdown method will cause this function to exit.
- */
- void eventLoop();
-
- //! Adds an Client to the client list for lookups
- void addClient(Window window, Client *client);
-
- //! Removes an Client from the client list for lookups
- void removeClient(Window window);
-
- //! Finds an Client based on its window id
- Client *findClient(Window window);
-
- //! The client with input focus
- inline Client *focusedClient() { return _focused_client; }
-
- //! Change the client which has focus.
- /*!
- This is called by the clients themselves when their focus state changes.
- */
- void setFocusedClient(Client *c);
-
- //! The screen with input focus
- inline Screen *focusedScreen() { return _focused_screen; }
-
- //! Requests that the window manager exit
- /*!
- Causes the Openbox::eventLoop function to stop looping, so that the window
- manager can be destroyed.
- */
- inline void shutdown() { _shutdown = true; }
-
- inline void restart(const std::string &bin = "") {
- _shutdown = true; _restart = true; _restart_prog = bin;
- }
-
- //! True if Openbox should be restarted instead of exiting
- inline bool doRestart() const { return _restart; }
-
- //! The command line requested to be executed in place of restarting
- //! Openbox the way it was run previously.
- inline const std::string &restartProgram() const { return _restart_prog; }
-};
-
-}
-
-#endif // __openbox_hh
diff --git a/src/python.cc b/src/python.cc
deleted file mode 100644
index 75b7cc13..00000000
--- a/src/python.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#include "python.hh"
-#include "openbox.hh"
-#include "actions.hh"
-#include "python.hh"
-#include "bindings.hh"
-#include "otk/display.hh"
-#include "otk/util.hh"
-
-extern "C" {
-#include <Python.h>
-
-#include "gettext.h"
-#define _(str) gettext(str)
-}
-
-namespace ob {
-
-static PyObject *get = NULL;
-
-void python_init(char *argv0)
-{
- // start the python engine
- Py_SetProgramName(argv0);
- Py_Initialize();
- // prepend the openbox directories for python scripts to the sys path
- PyRun_SimpleString("import sys");
- PyRun_SimpleString("sys.path.insert(0, '" SCRIPTDIR "')");
- PyRun_SimpleString(const_cast<char*>(("sys.path.insert(0, '" +
- otk::expandTilde("~/.openbox/python") +
- "')").c_str()));
-
- return;
- PyObject *obmodule = PyImport_ImportModule("config");
- if (obmodule == NULL) {
- PyErr_Print();
- return;
- }
- PyObject *configdict = PyModule_GetDict(obmodule);
- Py_DECREF(obmodule);
-
- get = PyDict_GetItemString(configdict, "get");
- if (get == NULL) {
- PyErr_Print();
- return;
- }
-}
-
-void python_destroy()
-{
- Py_Finalize();
-}
-
-int python_exec(const std::string &path)
-{
- FILE *rcpyfd = fopen(path.c_str(), "r");
- if (!rcpyfd) {
- fprintf(stderr, _("Unabled to open python file %s\n"), path.c_str());
- return 1;
- }
-
- //PyRun_SimpleFile(rcpyfd, const_cast<char*>(path.c_str()));
-
- PyObject *module = PyImport_AddModule("__main__");
- assert(module);
- PyObject *dict = PyModule_GetDict(module);
- assert(dict);
- PyObject *result = PyRun_File(rcpyfd, const_cast<char*>(path.c_str()),
- Py_file_input, dict, dict);
- int ret = result == NULL ? 2 : 0;
- if (result == NULL)
- PyErr_Print();
-
- Py_XDECREF(result);
-
- Py_DECREF(dict);
-
- fclose(rcpyfd);
- return ret;
-}
-
-bool python_get_long(const char *name, long *value)
-{
- return false;
- if (get == NULL) return false;
- bool ret = false;
-
- PyObject *val = PyObject_CallFunction(get, "ss", "openbox", name);
- if (val == NULL)
- PyErr_Print();
- else if (PyInt_Check(val)) {
- *value = PyInt_AsLong(val);
- ret = true;
- } else if (PyLong_Check(val)) {
- *value = PyLong_AsLong(val);
- ret = true;
- }
- Py_XDECREF(val);
- return ret;
-}
-
-bool python_get_string(const char *name, otk::ustring *value)
-{
- return false;
- if (get == NULL) return false;
- bool ret = false;
-
- PyObject *val = PyObject_CallFunction(get, "ss", "openbox", name);
- if (val == NULL)
- PyErr_Print();
- else if (PyString_Check(val)) {
- *value = std::string(PyString_AsString(val), PyString_Size(val));
- ret = true;
- }
- Py_XDECREF(val);
- return ret;
-}
-
-bool python_get_stringlist(const char *name, std::vector<otk::ustring> *value)
-{
- return false;
- if (get == NULL) return false;
- bool ret = false;
-
- PyObject *val = PyObject_CallFunction(get, "ss", "openbox", name);
- if (val == NULL)
- PyErr_Print();
- else if (PyList_Check(val)) {
- for (int i = 0, end = PyList_Size(val); i < end; ++i) {
- PyObject *str = PyList_GET_ITEM(val, i);
- if (PyString_Check(str))
- value->push_back(std::string(PyString_AsString(str),
- PyString_Size(str)));
- }
- }
- Py_XDECREF(val);
- return ret;
-}
-
-}
diff --git a/src/python.hh b/src/python.hh
deleted file mode 100644
index c1655503..00000000
--- a/src/python.hh
+++ /dev/null
@@ -1,243 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef __python_hh
-#define __python_hh
-
-/*! @file python.hh
- @brief wee
-*/
-
-#include "otk/point.hh"
-#include "otk/rect.hh"
-#include "otk/property.hh"
-#include "otk/display.hh"
-#include "otk/ustring.hh"
-
-extern "C" {
-#include <X11/Xlib.h>
-}
-
-#include <string>
-#include <vector>
-
-
-namespace ob {
-
-class Client;
-
-struct MouseContext {
- enum MC {
- Frame,
- Titlebar,
- Handle,
- Window,
- IconButton,
- MaximizeButton,
- CloseButton,
- IconifyButton,
- AllDesktopsButton,
- Grip,
- Root,
- MenuItem
-#ifndef DOXYGEN_IGNORE
- , NUM_MOUSE_CONTEXT
-#endif
- };
-};
-
-struct MouseAction {
- enum MA {
- Press,
- Release,
- Click,
- DoubleClick,
- Motion
-#ifndef DOXYGEN_IGNORE
- , NUM_MOUSE_ACTION
-#endif
- };
-};
-
-struct KeyContext {
- enum KC {
- Menu,
- All
-#ifndef DOXYGEN_IGNORE
- , NUM_KEY_CONTEXT
-#endif
- };
-};
-
-struct KeyAction {
- enum KA {
- Press,
- Release
-#ifndef DOXYGEN_IGNORE
- , NUM_KEY_ACTION
-#endif
- };
-};
-
-struct EventAction {
- enum EA {
- EnterWindow, //!< Occurs when the mouse enters a window
- LeaveWindow, //!< Occurs when the mouse leaves a window
- //! Occurs while a window is being managed. The handler should call
- //! Client::move on the window
- PlaceWindow,
- //! Occurs while a window is being managed, just before the window is
- //! displayed
- /*!
- Note that the window's state may not be completely stabilized by this
- point. The NewWindow event should be used when possible.
- */
- DisplayingWindow,
- //! Occurs when a window is finished being managed
- NewWindow,
- //! Occurs when a window has been closed and is going to be unmanaged
- CloseWindow,
- //! Occurs when the window manager manages a screen
- /*!
- This event occurs on each managed screen during startup.
- */
- Startup,
- //! Occurs when the window manager unmanages a screen
- /*!
- This event occurs on each managed screen during shutdown.
- */
- Shutdown,
- //! Occurs when the input focus target changes
- /*!
- The data.client will be None of no client is focused.
- */
- Focus,
- //! Occurs when the system is fired through X.
- /*!
- The data.client will hold the client associated with the bell if
- one has been specified, or None.
- */
- Bell,
- //! Occurs when a client toggles its urgent status.
- /*!
- The Client::urgent method can be used to get the status.
- */
- UrgentWindow
-#ifndef DOXYGEN_IGNORE
- , NUM_EVENT_ACTION
-#endif
- };
-};
-
-class MouseData {
-public:
- int screen;
- Client *client;
- Time time;
- unsigned int state;
- unsigned int button;
- MouseContext::MC context;
- MouseAction::MA action;
- int xroot;
- int yroot;
- int pressx;
- int pressy;
- int press_clientx;
- int press_clienty;
- int press_clientwidth;
- int press_clientheight;
-
- MouseData(int screen, Client *client, Time time, unsigned int state,
- unsigned int button, MouseContext::MC context,
- MouseAction::MA action, int xroot, int yroot,
- const otk::Point &initpos, const otk::Rect &initarea) {
- this->screen = screen;
- this->client = client;
- this->time = time;
- this->state = state;
- this->button = button;
- this->context= context;
- this->action = action;
- this->xroot = xroot;
- this->yroot = yroot;
- this->pressx = initpos.x();
- this->pressy = initpos.y();
- this->press_clientx = initarea.x();
- this->press_clienty = initarea.y();
- this->press_clientwidth = initarea.width();
- this->press_clientheight = initarea.height();
- }
- MouseData(int screen, Client *client, Time time, unsigned int state,
- unsigned int button, MouseContext::MC context,
- MouseAction::MA action) {
- this->screen = screen;
- this->client = client;
- this->time = time;
- this->state = state;
- this->button = button;
- this->context= context;
- this->action = action;
- this->xroot = xroot;
- this->yroot = yroot;
- this->pressx = 0;
- this->pressy = 0;
- this->press_clientx = 0;
- this->press_clienty = 0;
- this->press_clientwidth = 0;
- this->press_clientheight = 0;
- }
-};
-
-class EventData {
-public:
- int screen;
- Client *client;
- unsigned int state;
- EventAction::EA action;
-
- EventData(int screen, Client *client, EventAction::EA action,
- unsigned int state) {
- this->screen = screen;
- this->client = client;
- this->action = action;
- this->state = state;
- }
-};
-
-class KeyData {
-public:
- int screen;
- Client *client;
- Time time;
- unsigned int state;
- char *key;
- KeyAction::KA action;
-
- KeyData(int screen, Client *client, Time time, unsigned int state,
- unsigned int key, KeyAction::KA action) {
- this->screen = screen;
- this->client = client;
- this->time = time;
- this->state = state;
- this->key = XKeysymToString(XKeycodeToKeysym(**otk::display,
- key, 0));
- this->action = action;
- }
-};
-
-// The void*'s will be used to hold the native language's function pointer
-typedef void (*MouseCallback)(MouseData*, void*);
-typedef void (*KeyCallback)(KeyData*, void*);
-typedef void (*EventCallback)(EventData*, void*);
-
-void python_init(char *argv0);
-void python_destroy();
-//! Returns 0 for success, 1 for failing to open the file, 2 for an exception
-int python_exec(const std::string &path);
-
-bool python_get_long(const char *name, long *value);
-bool python_get_string(const char *name, otk::ustring *value);
-bool python_get_stringlist(const char *name, std::vector<otk::ustring> *value);
-
-}
-
-
-#endif // __python_hh
diff --git a/src/screen.cc b/src/screen.cc
deleted file mode 100644
index 16e37df6..00000000
--- a/src/screen.cc
+++ /dev/null
@@ -1,945 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#include "config.h"
-
-#include "screen.hh"
-#include "client.hh"
-#include "openbox.hh"
-#include "frame.hh"
-#include "bindings.hh"
-#include "python.hh"
-#include "otk/display.hh"
-#include "otk/property.hh"
-#include "otk/util.hh"
-
-extern "C" {
-#ifdef HAVE_UNISTD_H
-# include <sys/types.h>
-# include <unistd.h>
-#endif // HAVE_UNISTD_H
-
-#include "gettext.h"
-#define _(str) gettext(str)
-}
-
-#include <vector>
-#include <algorithm>
-#include <cstdio>
-#include <cstring>
-
-static bool running;
-static int anotherWMRunning(Display *display, XErrorEvent *) {
- printf(_("Another window manager already running on display %s.\n"),
- DisplayString(display));
- running = true;
- return -1;
-}
-
-
-namespace ob {
-
-
-Screen::Screen(int screen)
- : _number(screen)
-{
- assert(screen >= 0); assert(screen < ScreenCount(**otk::display));
- _info = otk::display->screenInfo(screen);
-
- ::running = false;
- XErrorHandler old = XSetErrorHandler(::anotherWMRunning);
- XSelectInput(**otk::display, _info->rootWindow(),
- Screen::event_mask);
- XSync(**otk::display, false);
- XSetErrorHandler(old);
-
- _managed = !::running;
- if (! _managed) return; // was unable to manage the screen
-
-#ifdef DEBUG
- printf(_("Managing screen %d: visual 0x%lx, depth %d\n"),
- _number, XVisualIDFromVisual(_info->visual()), _info->depth());
-#endif
-
- otk::Property::set(_info->rootWindow(), otk::Property::atoms.openbox_pid,
- otk::Property::atoms.cardinal, (unsigned long) getpid());
-
- // set the mouse cursor for the root window (the default cursor)
- XDefineCursor(**otk::display, _info->rootWindow(),
- openbox->cursors().session);
-
- // set up notification of netwm support
- changeSupportedAtoms();
-
- // Set the netwm properties for geometry
- unsigned long geometry[] = { _info->size().width(),
- _info->size().height() };
- otk::Property::set(_info->rootWindow(),
- otk::Property::atoms.net_desktop_geometry,
- otk::Property::atoms.cardinal, geometry, 2);
-
- _desktop = 0;
-
- changeNumDesktops(4); // set the hint
- changeDesktop(0); // set the hint
-
- // don't start in showing-desktop mode
- _showing_desktop = false;
- otk::Property::set(_info->rootWindow(),
- otk::Property::atoms.net_showing_desktop,
- otk::Property::atoms.cardinal, 0);
-
- // create the window which gets focus when no clients get it
- XSetWindowAttributes attr;
- attr.override_redirect = true;
- _focuswindow = XCreateWindow(**otk::display, _info->rootWindow(),
- -100, -100, 1, 1, 0, 0, InputOnly,
- _info->visual(), CWOverrideRedirect, &attr);
- XMapRaised(**otk::display, _focuswindow);
-
- // these may be further updated if any pre-existing windows are found in
- // the manageExising() function
- changeClientList(); // initialize the client lists, which will be empty
-
- updateDesktopLayout();
-
- // register this class as the event handler for the root window
- openbox->registerHandler(_info->rootWindow(), this);
-
- // call the python Startup callbacks
- EventData data(_number, 0, EventAction::Startup, 0);
- openbox->bindings()->fireEvent(&data);
-}
-
-
-Screen::~Screen()
-{
- if (! _managed) return;
-
- XSelectInput(**otk::display, _info->rootWindow(), NoEventMask);
-
- // unmanage all windows
- while (!clients.empty())
- unmanageWindow(clients.front());
-
- // call the python Shutdown callbacks
- EventData data(_number, 0, EventAction::Shutdown, 0);
- openbox->bindings()->fireEvent(&data);
-
- XDestroyWindow(**otk::display, _focuswindow);
- XDestroyWindow(**otk::display, _supportwindow);
-}
-
-
-void Screen::manageExisting()
-{
- unsigned int i, j, nchild;
- Window r, p, *children;
- XQueryTree(**otk::display, _info->rootWindow(), &r, &p,
- &children, &nchild);
-
- // preen the window list of all icon windows... for better dockapp support
- for (i = 0; i < nchild; i++) {
- if (children[i] == None) continue;
-
- XWMHints *wmhints = XGetWMHints(**otk::display,
- children[i]);
-
- if (wmhints) {
- if ((wmhints->flags & IconWindowHint) &&
- (wmhints->icon_window != children[i])) {
- for (j = 0; j < nchild; j++) {
- if (children[j] == wmhints->icon_window) {
- children[j] = None;
- break;
- }
- }
- }
-
- XFree(wmhints);
- }
- }
-
- // manage shown windows
- for (i = 0; i < nchild; ++i) {
- if (children[i] == None)
- continue;
-
- XWindowAttributes attrib;
- if (XGetWindowAttributes(**otk::display, children[i], &attrib)) {
- if (attrib.override_redirect) continue;
-
- if (attrib.map_state != IsUnmapped) {
- manageWindow(children[i]);
- }
- }
- }
-
- XFree(children);
-}
-
-void Screen::updateDesktopLayout()
-{
- //const unsigned long _NET_WM_ORIENTATION_HORZ = 0;
- const unsigned long _NET_WM_ORIENTATION_VERT = 1;
- //const unsigned long _NET_WM_TOPLEFT = 0;
- const unsigned long _NET_WM_TOPRIGHT = 1;
- const unsigned long _NET_WM_BOTTOMRIGHT = 2;
- const unsigned long _NET_WM_BOTTOMLEFT = 3;
-
- // defaults
- _layout.orientation = DesktopLayout::Horizontal;
- _layout.start_corner = DesktopLayout::TopLeft;
- _layout.rows = 1;
- _layout.columns = _num_desktops;
-
- unsigned long *data, num = 4;
- if (otk::Property::get(_info->rootWindow(),
- otk::Property::atoms.net_desktop_layout,
- otk::Property::atoms.cardinal,
- &num, &data)) {
- if (num == 4) {
- if (data[0] == _NET_WM_ORIENTATION_VERT)
- _layout.orientation = DesktopLayout::Vertical;
- if (data[3] == _NET_WM_TOPRIGHT)
- _layout.start_corner = DesktopLayout::TopRight;
- else if (data[3] == _NET_WM_BOTTOMRIGHT)
- _layout.start_corner = DesktopLayout::BottomRight;
- else if (data[3] == _NET_WM_BOTTOMLEFT)
- _layout.start_corner = DesktopLayout::BottomLeft;
-
- // fill in a zero rows/columns
- if (!(data[1] == 0 && data[2] == 0)) { // both 0's is bad data..
- if (data[1] == 0) {
- data[1] = (_num_desktops + _num_desktops % data[2]) / data[2];
- } else if (data[2] == 0) {
- data[2] = (_num_desktops + _num_desktops % data[1]) / data[1];
- }
- _layout.columns = data[1];
- _layout.rows = data[2];
- }
-
- // bounds checking
- if (_layout.orientation == DesktopLayout::Horizontal) {
- if (_layout.rows > _num_desktops) _layout.rows = _num_desktops;
- if (_layout.columns > (_num_desktops + _num_desktops % _layout.rows) /
- _layout.rows)
- _layout.columns = (_num_desktops + _num_desktops % _layout.rows) /
- _layout.rows;
- } else {
- if (_layout.columns > _num_desktops) _layout.columns = _num_desktops;
- if (_layout.rows > (_num_desktops + _num_desktops % _layout.columns) /
- _layout.columns)
- _layout.rows = (_num_desktops + _num_desktops % _layout.columns) /
- _layout.columns;
- }
- }
- delete [] data;
- }
-}
-
-void Screen::updateStruts()
-{
- struct ApplyStrut {
- void operator()(otk::Strut &self, const otk::Strut &other) {
- self.left = std::max(self.left, other.left);
- self.right = std::max(self.right, other.right);
- self.top = std::max(self.top, other.top);
- self.bottom = std::max(self.bottom, other.bottom);
- }
- } apply;
-
- StrutList::iterator sit, send = _struts.end();
- // reset them all
- for (sit = _struts.begin(); sit != send; ++sit)
- sit->left = sit->right = sit->top = sit->bottom = 0;
-
- std::list<Client*>::const_iterator it, end = clients.end();
- for (it = clients.begin(); it != end; ++it) {
- if ((*it)->iconic()) continue; // these dont count in the strut
-
- unsigned int desk = (*it)->desktop();
- const otk::Strut &s = (*it)->strut();
-
- if (desk == 0xffffffff)
- for (unsigned int i = 0, e = _struts.size(); i < e; ++i)
- apply(_struts[i], s);
- else if (desk < _struts.size())
- apply(_struts[desk], s);
- else
- assert(false); // invalid desktop otherwise..
- // apply to the 'all desktops' strut
- apply(_struts.back(), s);
- }
- changeWorkArea();
-}
-
-
-void Screen::changeWorkArea()
-{
- unsigned long *dims = new unsigned long[4 * _num_desktops];
- for (unsigned int i = 0; i < _num_desktops + 1; ++i) {
- otk::Rect old_area = _area[i];
-/*
-#ifdef XINERAMA
- // reset to the full areas
- if (isXineramaActive())
- xineramaUsableArea = getXineramaAreas();
-#endif // XINERAMA
-*/
-
- _area[i] = otk::Rect(_struts[i].left, _struts[i].top,
- _info->size().width() - (_struts[i].left +
- _struts[i].right),
- _info->size().height() - (_struts[i].top +
- _struts[i].bottom));
-
-/*
-#ifdef XINERAMA
- if (isXineramaActive()) {
- // keep each of the ximerama-defined areas inside the strut
- RectList::iterator xit, xend = xineramaUsableArea.end();
- for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
- if (xit->x() < usableArea.x()) {
- xit->setX(usableArea.x());
- xit->setWidth(xit->width() - usableArea.x());
- }
- if (xit->y() < usableArea.y()) {
- xit->setY(usableArea.y());
- xit->setHeight(xit->height() - usableArea.y());
- }
- if (xit->x() + xit->width() > usableArea.width())
- xit->setWidth(usableArea.width() - xit->x());
- if (xit->y() + xit->height() > usableArea.height())
- xit->setHeight(usableArea.height() - xit->y());
- }
- }
-#endif // XINERAMA
-*/
- if (old_area != _area[i]) {
- // the area has changed, adjust all the maximized windows
- std::list<Client*>::iterator it, end = clients.end();
- for (it = clients.begin(); it != end; ++it)
- if (i < _num_desktops) {
- if ((*it)->desktop() == i)
- (*it)->remaximize();
- } else {
- // the 'all desktops' size
- if ((*it)->desktop() == 0xffffffff)
- (*it)->remaximize();
- }
- }
-
- // don't set these for the 'all desktops' area
- if (i < _num_desktops) {
- dims[(i * 4) + 0] = _area[i].x();
- dims[(i * 4) + 1] = _area[i].y();
- dims[(i * 4) + 2] = _area[i].width();
- dims[(i * 4) + 3] = _area[i].height();
- }
- }
- otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_workarea,
- otk::Property::atoms.cardinal, dims, 4 * _num_desktops);
- delete [] dims;
-}
-
-
-void Screen::changeSupportedAtoms()
-{
- // create the netwm support window
- _supportwindow = XCreateSimpleWindow(**otk::display,
- _info->rootWindow(),
- 0, 0, 1, 1, 0, 0, 0);
-
- // set supporting window
- otk::Property::set(_info->rootWindow(),
- otk::Property::atoms.net_supporting_wm_check,
- otk::Property::atoms.window, _supportwindow);
-
- //set properties on the supporting window
- otk::Property::set(_supportwindow, otk::Property::atoms.net_wm_name,
- otk::Property::utf8, "Openbox");
- otk::Property::set(_supportwindow,
- otk::Property::atoms.net_supporting_wm_check,
- otk::Property::atoms.window, _supportwindow);
-
-
- Atom supported[] = {
- otk::Property::atoms.net_current_desktop,
- otk::Property::atoms.net_number_of_desktops,
- otk::Property::atoms.net_desktop_geometry,
- otk::Property::atoms.net_desktop_viewport,
- otk::Property::atoms.net_active_window,
- otk::Property::atoms.net_workarea,
- otk::Property::atoms.net_client_list,
- otk::Property::atoms.net_client_list_stacking,
- otk::Property::atoms.net_desktop_names,
- otk::Property::atoms.net_close_window,
- otk::Property::atoms.net_desktop_layout,
- otk::Property::atoms.net_showing_desktop,
- otk::Property::atoms.net_wm_name,
- otk::Property::atoms.net_wm_visible_name,
- otk::Property::atoms.net_wm_icon_name,
- otk::Property::atoms.net_wm_visible_icon_name,
- otk::Property::atoms.net_wm_desktop,
- otk::Property::atoms.net_wm_strut,
- otk::Property::atoms.net_wm_window_type,
- otk::Property::atoms.net_wm_window_type_desktop,
- otk::Property::atoms.net_wm_window_type_dock,
- otk::Property::atoms.net_wm_window_type_toolbar,
- otk::Property::atoms.net_wm_window_type_menu,
- otk::Property::atoms.net_wm_window_type_utility,
- otk::Property::atoms.net_wm_window_type_splash,
- otk::Property::atoms.net_wm_window_type_dialog,
- otk::Property::atoms.net_wm_window_type_normal,
-/*
- otk::Property::atoms.net_wm_moveresize,
- otk::Property::atoms.net_wm_moveresize_size_topleft,
- otk::Property::atoms.net_wm_moveresize_size_topright,
- otk::Property::atoms.net_wm_moveresize_size_bottomleft,
- otk::Property::atoms.net_wm_moveresize_size_bottomright,
- otk::Property::atoms.net_wm_moveresize_move,
-*/
- otk::Property::atoms.net_wm_allowed_actions,
- otk::Property::atoms.net_wm_action_move,
- otk::Property::atoms.net_wm_action_resize,
- otk::Property::atoms.net_wm_action_minimize,
- otk::Property::atoms.net_wm_action_shade,
-/* otk::Property::atoms.net_wm_action_stick,*/
- otk::Property::atoms.net_wm_action_maximize_horz,
- otk::Property::atoms.net_wm_action_maximize_vert,
- otk::Property::atoms.net_wm_action_fullscreen,
- otk::Property::atoms.net_wm_action_change_desktop,
- otk::Property::atoms.net_wm_action_close,
-
- otk::Property::atoms.net_wm_state,
- otk::Property::atoms.net_wm_state_modal,
- otk::Property::atoms.net_wm_state_maximized_vert,
- otk::Property::atoms.net_wm_state_maximized_horz,
- otk::Property::atoms.net_wm_state_shaded,
- otk::Property::atoms.net_wm_state_skip_taskbar,
- otk::Property::atoms.net_wm_state_skip_pager,
- otk::Property::atoms.net_wm_state_hidden,
- otk::Property::atoms.net_wm_state_fullscreen,
- otk::Property::atoms.net_wm_state_above,
- otk::Property::atoms.net_wm_state_below,
- };
- const int num_supported = sizeof(supported)/sizeof(Atom);
-
- otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_supported,
- otk::Property::atoms.atom, supported, num_supported);
-}
-
-
-void Screen::changeClientList()
-{
- Window *windows;
- unsigned int size = clients.size();
-
- // create an array of the window ids
- if (size > 0) {
- Window *win_it;
-
- windows = new Window[size];
- win_it = windows;
- std::list<Client*>::const_iterator it = clients.begin();
- const std::list<Client*>::const_iterator end = clients.end();
- for (; it != end; ++it, ++win_it)
- *win_it = (*it)->window();
- } else
- windows = (Window*) 0;
-
- otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_client_list,
- otk::Property::atoms.window, windows, size);
-
- if (size)
- delete [] windows;
-
- changeStackingList();
-}
-
-
-void Screen::changeStackingList()
-{
- Window *windows;
- unsigned int size = _stacking.size();
-
- assert(size == clients.size()); // just making sure.. :)
-
-
- // create an array of the window ids (from bottom to top, reverse order!)
- if (size > 0) {
- Window *win_it;
-
- windows = new Window[size];
- win_it = windows;
- std::list<Client*>::const_reverse_iterator it = _stacking.rbegin();
- const std::list<Client*>::const_reverse_iterator end = _stacking.rend();
- for (; it != end; ++it, ++win_it)
- *win_it = (*it)->window();
- } else
- windows = (Window*) 0;
-
- otk::Property::set(_info->rootWindow(),
- otk::Property::atoms.net_client_list_stacking,
- otk::Property::atoms.window, windows, size);
-
- if (size)
- delete [] windows;
-}
-
-
-void Screen::manageWindow(Window window)
-{
- Client *client = 0;
- XWMHints *wmhint;
- XSetWindowAttributes attrib_set;
- XEvent e;
- XWindowAttributes attrib;
-
- otk::display->grab();
-
- // check if it has already been unmapped by the time we started mapping
- // the grab does a sync so we don't have to here
- if (XCheckTypedWindowEvent(**otk::display, window, DestroyNotify, &e) ||
- XCheckTypedWindowEvent(**otk::display, window, UnmapNotify, &e)) {
- XPutBackEvent(**otk::display, &e);
-
- otk::display->ungrab();
- return; // don't manage it
- }
-
- if (!XGetWindowAttributes(**otk::display, window, &attrib) ||
- attrib.override_redirect) {
- otk::display->ungrab();
- return; // don't manage it
- }
-
- // is the window a docking app
- if ((wmhint = XGetWMHints(**otk::display, window))) {
- if ((wmhint->flags & StateHint) &&
- wmhint->initial_state == WithdrawnState) {
- //slit->addClient(w); // XXX: make dock apps work!
-
- otk::display->ungrab();
- XFree(wmhint);
- return;
- }
- XFree(wmhint);
- }
-
- // choose the events we want to receive on the CLIENT window
- attrib_set.event_mask = Client::event_mask;
- attrib_set.do_not_propagate_mask = Client::no_propagate_mask;
- XChangeWindowAttributes(**otk::display, window,
- CWEventMask|CWDontPropagate, &attrib_set);
-
- // create the Client class, which gets all of the hints on the window
- client = new Client(_number, window);
- // register for events
- openbox->registerHandler(window, client);
- // add to the wm's map
- openbox->addClient(window, client);
-
- // we dont want a border on the client
- client->toggleClientBorder(false);
-
- // specify that if we exit, the window should not be destroyed and should be
- // reparented back to root automatically
- XChangeSaveSet(**otk::display, window, SetModeInsert);
-
- // create the decoration frame for the client window
- client->frame = new Frame(client);
- // register the plate for events (map req's)
- // this involves removing itself from the handler list first, since it is
- // auto added to the list, being a widget. we won't get any events on the
- // plate except for events for the client (SubstructureRedirectMask)
- openbox->clearHandler(client->frame->plate());
- openbox->registerHandler(client->frame->plate(), client);
-
- // add to the wm's map
- Window *w = client->frame->allWindows();
- for (unsigned int i = 0; w[i]; ++i)
- openbox->addClient(w[i], client);
- delete [] w;
-
- // reparent the client to the frame
- client->frame->grabClient();
-
- if (openbox->state() != Openbox::State_Starting) {
- // position the window intelligenty .. hopefully :)
- // call the python PLACEWINDOW binding
- EventData data(_number, client, EventAction::PlaceWindow, 0);
- openbox->bindings()->fireEvent(&data);
- }
-
- EventData ddata(_number, client, EventAction::DisplayingWindow, 0);
- openbox->bindings()->fireEvent(&ddata);
-
- client->showhide();
-
- client->applyStartupState();
-
- otk::display->ungrab();
-
- // add to the screen's list
- clients.push_back(client);
- // once the client is in the list, update our strut to include the new
- // client's (it is good that this happens after window placement!)
- updateStruts();
- // this puts into the stacking order, then raises it
- _stacking.push_back(client);
- raiseWindow(client);
- // update the root properties
- changeClientList();
-
- openbox->bindings()->grabButtons(true, client);
-
- EventData ndata(_number, client, EventAction::NewWindow, 0);
- openbox->bindings()->fireEvent(&ndata);
-
-#ifdef DEBUG
- printf("Managed window 0x%lx frame 0x%lx\n",
- window, client->frame->window());
-#endif
-}
-
-
-void Screen::unmanageWindow(Client *client)
-{
- Frame *frame = client->frame;
-
- // call the python CLOSEWINDOW binding
- EventData data(_number, client, EventAction::CloseWindow, 0);
- openbox->bindings()->fireEvent(&data);
-
- openbox->bindings()->grabButtons(false, client);
-
- // remove from the wm's map
- openbox->removeClient(client->window());
- Window *w = frame->allWindows();
- for (unsigned int i = 0; w[i]; ++i)
- openbox->addClient(w[i], client);
- delete [] w;
- // unregister for handling events
- openbox->clearHandler(client->window());
-
- // remove the window from our save set
- XChangeSaveSet(**otk::display, client->window(), SetModeDelete);
-
- // we dont want events no more
- XSelectInput(**otk::display, client->window(), NoEventMask);
-
- frame->hide();
-
- // give the client its border back
- client->toggleClientBorder(true);
-
- // reparent the window out of the frame
- frame->releaseClient();
-
-#ifdef DEBUG
- Window framewin = client->frame->window();
-#endif
- delete client->frame;
- client->frame = 0;
-
- // remove from the stacking order
- _stacking.remove(client);
-
- // remove from the screen's list
- clients.remove(client);
-
- // once the client is out of the list, update our strut to remove it's
- // influence
- updateStruts();
-
- // unset modal before dropping our focus
- client->_modal = false;
-
- // unfocus the client (calls the focus callbacks)
- if (client->focused()) client->unfocus();
-
-#ifdef DEBUG
- printf("Unmanaged window 0x%lx frame 0x%lx\n", client->window(), framewin);
-#endif
-
- delete client;
-
- // update the root properties
- changeClientList();
-}
-
-void Screen::lowerWindow(Client *client)
-{
- Window wins[2]; // only ever restack 2 windows.
-
- assert(!_stacking.empty()); // this would be bad
-
- std::list<Client*>::iterator it = --_stacking.end();
- const std::list<Client*>::iterator end = _stacking.begin();
-
- if (client->modal() && client->transientFor()) {
- // don't let a modal window lower below its transient_for
- it = std::find(_stacking.begin(), _stacking.end(), client->transientFor());
- assert(it != _stacking.end());
-
- wins[0] = (it == _stacking.begin() ? _focuswindow :
- ((*(--std::list<Client*>::const_iterator(it)))->
- frame->window()));
- wins[1] = client->frame->window();
- if (wins[0] == wins[1]) return; // already right above the window
-
- _stacking.remove(client);
- _stacking.insert(it, client);
- } else {
- for (; it != end && (*it)->layer() < client->layer(); --it);
- if (*it == client) return; // already the bottom, return
-
- wins[0] = (*it)->frame->window();
- wins[1] = client->frame->window();
-
- _stacking.remove(client);
- _stacking.insert(++it, client);
- }
-
- XRestackWindows(**otk::display, wins, 2);
- changeStackingList();
-}
-
-void Screen::raiseWindow(Client *client)
-{
- Window wins[2]; // only ever restack 2 windows.
-
- assert(!_stacking.empty()); // this would be bad
-
- Client *m = client->findModalChild();
- // if we have a modal child, raise it instead, we'll go along tho later
- if (m) raiseWindow(m);
-
- // remove the client before looking so we can't run into ourselves
- _stacking.remove(client);
-
- std::list<Client*>::iterator it = _stacking.begin();
- const std::list<Client*>::iterator end = _stacking.end();
-
- // the stacking list is from highest to lowest
- for (; it != end && ((*it)->layer() > client->layer() || m == *it); ++it);
-
- /*
- if our new position is the top, we want to stack under the _focuswindow
- otherwise, we want to stack under the previous window in the stack.
- */
- wins[0] = (it == _stacking.begin() ? _focuswindow :
- ((*(--std::list<Client*>::const_iterator(it)))->frame->window()));
- wins[1] = client->frame->window();
-
- _stacking.insert(it, client);
-
- XRestackWindows(**otk::display, wins, 2);
-
- changeStackingList();
-}
-
-void Screen::changeDesktop(unsigned int desktop)
-{
- if (desktop >= _num_desktops) return;
-
- printf("Moving to desktop %u\n", desktop);
-
- unsigned int old = _desktop;
-
- _desktop = desktop;
- otk::Property::set(_info->rootWindow(),
- otk::Property::atoms.net_current_desktop,
- otk::Property::atoms.cardinal, _desktop);
-
- if (old == _desktop) return;
-
- std::list<Client*>::iterator it, end = clients.end();
- for (it = clients.begin(); it != end; ++it)
- (*it)->showhide();
-
- // force the callbacks to fire
- if (!openbox->focusedClient())
- openbox->setFocusedClient(0);
-}
-
-void Screen::changeNumDesktops(unsigned int num)
-{
- assert(num > 0);
-
- if (!(num > 0)) return;
-
- // move windows on desktops that will no longer exist!
- std::list<Client*>::iterator it, end = clients.end();
- for (it = clients.begin(); it != end; ++it) {
- unsigned int d = (*it)->desktop();
- if (d >= num && d != 0xffffffff) {
- XEvent ce;
- ce.xclient.type = ClientMessage;
- ce.xclient.message_type = otk::Property::atoms.net_wm_desktop;
- ce.xclient.display = **otk::display;
- ce.xclient.window = (*it)->window();
- ce.xclient.format = 32;
- ce.xclient.data.l[0] = num - 1;
- XSendEvent(**otk::display, _info->rootWindow(), false,
- SubstructureNotifyMask | SubstructureRedirectMask, &ce);
- }
- }
-
- _num_desktops = num;
- otk::Property::set(_info->rootWindow(),
- otk::Property::atoms.net_number_of_desktops,
- otk::Property::atoms.cardinal, _num_desktops);
-
- // set the viewport hint
- unsigned long *viewport = new unsigned long[_num_desktops * 2];
- memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2);
- otk::Property::set(_info->rootWindow(),
- otk::Property::atoms.net_desktop_viewport,
- otk::Property::atoms.cardinal,
- viewport, _num_desktops * 2);
- delete [] viewport;
-
- // change our struts/area to match
- _area.resize(_num_desktops + 1);
- _struts.resize(_num_desktops + 1);
- updateStruts();
-
- // the number of rows/columns will differ
- updateDesktopLayout();
-
- // may be some unnamed desktops that we need to fill in with names
- updateDesktopNames();
-
- // change our desktop if we're on one that no longer exists!
- if (_desktop >= _num_desktops)
- changeDesktop(_num_desktops - 1);
-}
-
-
-void Screen::updateDesktopNames()
-{
- unsigned long num;
-
- if (!otk::Property::get(_info->rootWindow(),
- otk::Property::atoms.net_desktop_names,
- otk::Property::utf8, &num, &_desktop_names))
- _desktop_names.clear();
- while (_desktop_names.size() < _num_desktops)
- _desktop_names.push_back("Unnamed");
-}
-
-
-const otk::Rect& Screen::area(unsigned int desktop) const {
- assert(desktop < _num_desktops || desktop == 0xffffffff);
- if (desktop < _num_desktops)
- return _area[desktop];
- else
- return _area[_num_desktops];
-}
-
-void Screen::installColormap(bool install) const
-{
- if (install)
- XInstallColormap(**otk::display, _info->colormap());
- else
- XUninstallColormap(**otk::display, _info->colormap());
-}
-
-void Screen::showDesktop(bool show)
-{
- if (show == _showing_desktop) return; // no change
-
- // save the window focus, and restore it when leaving the show-desktop mode
- static Window saved_focus = 0;
- if (show) {
- Client *c = openbox->focusedClient();
- if (c) saved_focus = c->window();
- }
-
- _showing_desktop = show;
-
- std::list<Client*>::iterator it, end = clients.end();
- for (it = clients.begin(); it != end; ++it) {
- if ((*it)->type() == Client::Type_Desktop) {
- if (show)
- (*it)->focus();
- } else
- (*it)->showhide();
- }
-
- if (!show) {
- Client *f = openbox->focusedClient();
- if (!f || f->type() == Client::Type_Desktop) {
- Client *c = openbox->findClient(saved_focus);
- if (c) c->focus();
- }
- }
-
- otk::Property::set(_info->rootWindow(),
- otk::Property::atoms.net_showing_desktop,
- otk::Property::atoms.cardinal,
- show ? 1 : 0);
-}
-
-void Screen::propertyHandler(const XPropertyEvent &e)
-{
- otk::EventHandler::propertyHandler(e);
-
- // compress changes to a single property into a single change
- XEvent ce;
- while (XCheckTypedWindowEvent(**otk::display, _info->rootWindow(),
- e.type, &ce)) {
- // XXX: it would be nice to compress ALL changes to a property, not just
- // changes in a row without other props between.
- if (ce.xproperty.atom != e.atom) {
- XPutBackEvent(**otk::display, &ce);
- break;
- }
- }
-
- if (e.atom == otk::Property::atoms.net_desktop_names)
- updateDesktopNames();
- else if (e.atom == otk::Property::atoms.net_desktop_layout)
- updateDesktopLayout();
-}
-
-
-void Screen::clientMessageHandler(const XClientMessageEvent &e)
-{
- otk::EventHandler::clientMessageHandler(e);
-
- if (e.format != 32) return;
-
- if (e.message_type == otk::Property::atoms.net_current_desktop) {
- changeDesktop(e.data.l[0]);
- } else if (e.message_type == otk::Property::atoms.net_number_of_desktops) {
- changeNumDesktops(e.data.l[0]);
- } else if (e.message_type == otk::Property::atoms.net_showing_desktop) {
- showDesktop(e.data.l[0] != 0);
- }
-}
-
-
-void Screen::mapRequestHandler(const XMapRequestEvent &e)
-{
- otk::EventHandler::mapRequestHandler(e);
-
-#ifdef DEBUG
- printf("MapRequest for 0x%lx\n", e.window);
-#endif // DEBUG
-
- Client *c = openbox->findClient(e.window);
- if (c) {
-#ifdef DEBUG
- printf("DEBUG: MAP REQUEST CAUGHT IN SCREEN. IGNORED.\n");
-#endif
- } else {
- if (_showing_desktop)
- showDesktop(false); // leave showing-the-desktop mode
- manageWindow(e.window);
- }
-}
-
-}
diff --git a/src/screen.hh b/src/screen.hh
deleted file mode 100644
index 20ba0a63..00000000
--- a/src/screen.hh
+++ /dev/null
@@ -1,230 +0,0 @@
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-#ifndef __screen_hh
-#define __screen_hh
-
-/*! @file screen.hh
- @brief Screen manages a single screen
-*/
-
-extern "C" {
-#include <X11/Xlib.h>
-}
-
-#include "otk/strut.hh"
-#include "otk/rect.hh"
-#include "otk/screeninfo.hh"
-#include "otk/eventhandler.hh"
-#include "otk/property.hh"
-#include "otk/ustring.hh"
-
-#include <string>
-#include <list>
-
-namespace ob {
-
-class Client;
-
-struct DesktopLayout {
- enum Corner { TopLeft, TopRight, BottomRight, BottomLeft };
- enum Direction { Horizontal, Vertical };
-
- Direction orientation;
- Corner start_corner;
- unsigned int rows;
- unsigned int columns;
-};
-
-//! Manages a single screen
-/*!
-*/
-class Screen : public otk::EventHandler {
-public:
- //! Holds a list of otk::Strut objects
- typedef std::vector<otk::Strut> StrutList;
- //! Holds a list of otk::Rect objects
- typedef std::vector<otk::Rect> RectList;
-
- static const unsigned long event_mask = ColormapChangeMask |
- EnterWindowMask |
- LeaveWindowMask |
- PropertyChangeMask |
- SubstructureNotifyMask |
- SubstructureRedirectMask |
- ButtonPressMask |
- ButtonReleaseMask;
-
- //! All managed clients on the screen (in order of being mapped)
- std::list<Client*> clients;
-
-private:
- //! Was %Openbox able to manage the screen?
- bool _managed;
-
- //! The number of the screen on the X server
- int _number;
-
- //! Information about this screen
- const otk::ScreenInfo *_info;
-
- //! Area usable for placement etc (total - struts), one per desktop,
- //! plus one extra for windows on all desktops
- RectList _area;
-
- //! Combined strut from all of the clients' struts, one per desktop,
- //! plus one extra for windows on all desktops
- StrutList _struts;
-
- //! An offscreen window which gets focus when nothing else has it
- Window _focuswindow;
-
- //! An offscreen window which shows that a NETWM compliant window manager is
- //! running
- Window _supportwindow;
-
- //! A list of all managed clients on the screen, in their stacking order
- std::list<Client*> _stacking;
-
- //! The desktop currently being displayed
- unsigned int _desktop;
-
- //! The number of desktops
- unsigned int _num_desktops;
-
- //! The names of all desktops
- otk::Property::StringVect _desktop_names;
-
- //! The layout of the desktops as specified by an EWMH compliant pager
- DesktopLayout _layout;
-
- //! True when the window manager is in 'showing desktop' mode
- bool _showing_desktop;
-
- //! Calculate the Screen::_area member
- void calcArea();
- //! Set the list of supported NETWM atoms on the root window
- void changeSupportedAtoms();
- //! Set the client list on the root window
- /*!
- Sets the _NET_CLIENT_LIST root window property.<br>
- Also calls Screen::updateStackingList.
- */
- void changeClientList();
- //! Set the client stacking list on the root window
- /*!
- Set the _NET_CLIENT_LIST_STACKING root window property.
- */
- void changeStackingList();
- //! Set the work area hint on the root window
- /*!
- Set the _NET_WORKAREA root window property.
- */
- void changeWorkArea();
-
- //! Get desktop names from the root window property
- void updateDesktopNames();
-
- //! Gets the layout of the desktops from the root window property
- void updateDesktopLayout();
-
- //! Changes to the specified desktop, displaying windows on it and hiding
- //! windows on the others.
- /*!
- @param desktop The number of the desktop to switch to (starts from 0).
- If the desktop is out of valid range, it is ignored.
- */
- void changeDesktop(unsigned int desktop);
-
- //! Changes the number of desktops.
- /*!
- @param num The number of desktops that should exist. This value must be
- greater than 0 or it will be ignored.
- */
- void changeNumDesktops(unsigned int num);
-
-public:
- //! Constructs a new Screen object
- Screen(int screen);
- //! Destroys the Screen object
- virtual ~Screen();
-
- inline int number() const { return _number; }
-
- //! Returns if the screen was successfully managed
- /*!
- If this is false, then the screen should be deleted and should NOT be
- used.
- */
- inline bool managed() const { return _managed; }
-
- //! An offscreen window which gets focus when nothing else has it
- inline Window focuswindow() const { return _focuswindow; }
- //! Returns the desktop being displayed
- inline unsigned int desktop() const { return _desktop; }
- //! Returns the number of desktops
- inline unsigned int numDesktops() const { return _num_desktops; }
- //! When true, the desktop is being shown and all clients are hidden
- inline bool showingDesktop() const { return _showing_desktop; }
-
- //! Returns the area of the screen not reserved by applications' Struts
- /*!
- @param desktop The desktop number of the area to retrieve for. A value of
- 0xffffffff will return an area that combines all struts
- on all desktops.
- */
- const otk::Rect& area(unsigned int desktop) const;
-
- //! Gives the layout of how the desktops are being displayed, the number of
- //! rows and columns etc.
- const DesktopLayout& desktopLayout() const { return _layout; }
-
- //! Shows and focuses the desktop and hides all the client windows, or
- //! returns to the normal state, showing client windows.
- void showDesktop(bool show);
-
- //! Update's the screen's combined strut of all the clients.
- /*!
- Clients should call this whenever they change their strut.
- */
- void updateStruts();
-
- //! Manage any pre-existing windows on the screen
- void manageExisting();
- //! Manage a client window
- /*!
- This gives the window a frame, reparents it, selects events on it, etc.
- */
- void manageWindow(Window window);
- //! Unmanage a client
- /*!
- This removes the window's frame, reparents it to root, unselects events on
- it, etc.
- @param client The client to unmanage
- */
- void unmanageWindow(Client *client);
-
- //! Raises a client window above all others in its stacking layer
- /*!
- raiseWindow has a couple of constraints that lowerWindow does not.<br>
- 1) raiseWindow can be called after changing a Client's stack layer, and
- the list will be reorganized properly.<br>
- 2) raiseWindow guarantees that XRestackWindows() will <i>always</i> be
- called for the specified client.
- */
- void raiseWindow(Client *client);
-
- //! Lowers a client window below all others in its stacking layer
- void lowerWindow(Client *client);
-
- const otk::Property::StringVect& desktopNames() const
- { return _desktop_names; }
-
- void installColormap(bool install) const;
-
- virtual void propertyHandler(const XPropertyEvent &e);
- virtual void clientMessageHandler(const XClientMessageEvent &e);
- virtual void mapRequestHandler(const XMapRequestEvent &e);
-};
-
-}
-
-#endif// __screen_hh