From a52a6d96d701c993896f276e4198003317632aaf Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 21 Mar 2003 18:42:39 +0000 Subject: rm the old code including the .pys and the c++ shit --- src/.cvsignore | 5 - src/Makefile.am | 26 - src/actions.cc | 351 ---------- src/actions.hh | 79 --- src/bindings.cc | 655 ------------------ src/bindings.hh | 186 ----- src/client.cc | 2014 ------------------------------------------------------- src/client.hh | 759 --------------------- src/config.cc | 61 -- src/config.hh | 14 - src/frame.cc | 959 -------------------------- src/frame.hh | 203 ------ src/gettext.h | 70 -- src/main.cc | 51 -- src/openbox.cc | 413 ------------ src/openbox.hh | 250 ------- src/python.cc | 141 ---- src/python.hh | 243 ------- src/screen.cc | 945 -------------------------- src/screen.hh | 230 ------- 20 files changed, 7655 deletions(-) delete mode 100644 src/.cvsignore delete mode 100644 src/Makefile.am delete mode 100644 src/actions.cc delete mode 100644 src/actions.hh delete mode 100644 src/bindings.cc delete mode 100644 src/bindings.hh delete mode 100644 src/client.cc delete mode 100644 src/client.hh delete mode 100644 src/config.cc delete mode 100644 src/config.hh delete mode 100644 src/frame.cc delete mode 100644 src/frame.hh delete mode 100644 src/gettext.h delete mode 100644 src/main.cc delete mode 100644 src/openbox.cc delete mode 100644 src/openbox.hh delete mode 100644 src/python.cc delete mode 100644 src/python.hh delete mode 100644 src/screen.cc delete mode 100644 src/screen.hh (limited to 'src') 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 -#include - -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(h); - if (f) - context= f->mouseContext(e.window); - else if (dynamic_cast(h)) - context = MouseContext::Window; - else if (dynamic_cast(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(h); - if (f) - context= f->mouseContext(e.window); - else if (dynamic_cast(h)) - context = MouseContext::Window; - else if (dynamic_cast(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(h); - if (f) - context= f->mouseContext(e.window); - else if (dynamic_cast(h)) - context = MouseContext::Window; - else if (dynamic_cast(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 -#include -} - -#include - -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 - -#include "gettext.h" -#define _(str) gettext(str) -} - -#include -#include - -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(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 -#include -#include - -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 MouseCallbackList; -typedef std::list KeyCallbackList; -typedef std::list 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 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 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 -#include -#include - -#include "gettext.h" -#define _(str) gettext(str) -} - -#include // for memcpy -#include -#include -#include - -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(w / _min_ratio); - if (_max_ratio) - if (h * _max_ratio < w) h = static_cast(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 - -#ifdef SHAPE -#include -#endif // SHAPE -} - -#include -#include - -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. -

- 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 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.
- 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.
- 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.
- 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.
- 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.
- 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 -#endif // SHAPE -} - -#include "frame.hh" -#include "config.hh" -#include "openbox.hh" -#include "otk/display.hh" -#include "otk/surface.hh" - -#include -#include - -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 -} - -#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 -#include - -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 . - 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 - -#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 a NOP. We don't include - as well because people using "gettext.h" will not include , - and also including would fail on SunOS 4, whereas - is OK. */ -#if defined(__sun) -# include -#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 -# include -#endif // HAVE_UNISTD_H - -#include "gettext.h" -} - -#include "openbox.hh" -#include "otk/util.hh" - -#include -#include - -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 - -#ifdef HAVE_SIGNAL_H -# include -#endif // HAVE_SIGNAL_H - -#ifdef HAVE_FCNTL_H -# include -#endif // HAVE_FCNTL_H - -#ifdef HAVE_SYS_WAIT_H -# include -#endif // HAVE_SYS_WAIT_H - -#include "gettext.h" -#define _(str) gettext(str) -} - -#include -#include -#include - -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 use alternate resource file.\n\ - -menu use alternate menu file.\n\ - -script 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 -} - -#include -#include -#include - -#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 ClientMap; - - //! A list of Screen classes - typedef std::vector 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 - -#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(("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(path.c_str())); - - PyObject *module = PyImport_AddModule("__main__"); - assert(module); - PyObject *dict = PyModule_GetDict(module); - assert(dict); - PyObject *result = PyRun_File(rcpyfd, const_cast(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 *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 -} - -#include -#include - - -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 *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 -# include -#endif // HAVE_UNISTD_H - -#include "gettext.h" -#define _(str) gettext(str) -} - -#include -#include -#include -#include - -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::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::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::const_iterator it = clients.begin(); - const std::list::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::const_reverse_iterator it = _stacking.rbegin(); - const std::list::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::iterator it = --_stacking.end(); - const std::list::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::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::iterator it = _stacking.begin(); - const std::list::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::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::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::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::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 -} - -#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 -#include - -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 StrutList; - //! Holds a list of otk::Rect objects - typedef std::vector 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 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 _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.
- 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.
- 1) raiseWindow can be called after changing a Client's stack layer, and - the list will be reorganized properly.
- 2) raiseWindow guarantees that XRestackWindows() will always 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 -- cgit v1.2.3