X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fclient.cc;h=33e11ce07e1e596621acb3c61fe5070e8feabc38;hb=b18959e1bda52f807f62c95772c69ce3005215a7;hp=d5be00d01822b8b64f7796180eeea9f0035dfda0;hpb=17b0266979137ad957a701c7093a14841a8c2091;p=chaz%2Fopenbox diff --git a/src/client.cc b/src/client.cc index d5be00d0..33e11ce0 100644 --- a/src/client.cc +++ b/src/client.cc @@ -1,8 +1,6 @@ // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif +#include "config.h" #include "client.hh" #include "frame.hh" @@ -46,7 +44,6 @@ Client::Client(int screen, Window window) _urgent = false; _positioned = false; _disabled_decorations = 0; - _modal_child = 0; _group = None; _desktop = 0; @@ -480,7 +477,7 @@ void Client::updateNormalHints() _size_inc = otk::Size(1, 1); _base_size = otk::Size(0, 0); _min_size = otk::Size(0, 0); - _max_size = otk::Size(UINT_MAX, UINT_MAX); + _max_size = otk::Size(INT_MAX, INT_MAX); // get the hints from the window if (XGetWMNormalHints(**otk::display, _window, &size, &ret)) { @@ -641,7 +638,7 @@ void Client::updateStrut() // 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)->updateStrut(); + openbox->screen(_screen)->updateStruts(); } delete [] data; @@ -672,18 +669,11 @@ void Client::updateTransientFor() // if anything has changed... if (c != _transient_for) { - bool m = _modal; - if (_modal) - setModal(false); - 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 - - if (m) - setModal(true); } } @@ -740,107 +730,51 @@ void Client::setWMState(long state) switch (state) { case IconicState: - setDesktop(ICONIC_DESKTOP); + iconify(true); break; case NormalState: - setDesktop(openbox->screen(_screen)->desktop()); + iconify(false); break; } } -void Client::setDesktop(long target) +void Client::setDesktop(unsigned int target) { if (target == _desktop) return; - printf("Setting desktop %ld\n", target); + printf("Setting desktop %u\n", target); - if (!(target >= 0 || target == (signed)0xffffffff || - target == ICONIC_DESKTOP)) + if (!(target < openbox->screen(_screen)->numDesktops() || + target == 0xffffffff)) return; - + _desktop = target; - // set the desktop hint, but not if we're iconifying - if (_desktop != ICONIC_DESKTOP) - otk::Property::set(_window, otk::Property::atoms.net_wm_desktop, - otk::Property::atoms.cardinal, (unsigned)_desktop); + // set the desktop hint + otk::Property::set(_window, otk::Property::atoms.net_wm_desktop, + otk::Property::atoms.cardinal, _desktop); // 'move' the window to the new desktop - if (_desktop == openbox->screen(_screen)->desktop() || - _desktop == (signed)0xffffffff) - frame->show(); - else - frame->hide(); - - // Handle Iconic state. Iconic state is maintained by the client being a - // member of the ICONIC_DESKTOP, so this is where we make iconifying and - // uniconifying happen. - bool i = _desktop == ICONIC_DESKTOP; - if (i != _iconic) { // has the state changed? - _iconic = i; - 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 { - _wmstate = NormalState; - XMapWindow(**otk::display, _window); - } - changeState(); - } - - frame->adjustState(); + showhide(); + + openbox->screen(_screen)->updateStruts(); } -Client *Client::findModalChild(Client *skip) const +void Client::showhide() { - Client *ret = 0; - - // find a modal child recursively and try focus it - List::const_iterator it, end = _transients.end(); - for (it = _transients.begin(); it != end; ++it) - if ((*it)->_modal && *it != skip) - return *it; // got one - // none of our direct children are modal, let them try check - for (it = _transients.begin(); it != end; ++it) - if ((ret = (*it)->findModalChild())) - return ret; // got one - return ret; -} + 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; -void Client::setModal(bool modal) -{ - if (modal == _modal) return; - - if (modal) { - Client *c = this; - while (c->_transient_for) { - c = c->_transient_for; - if (c->_modal_child) break; // already has a modal child - c->_modal_child = this; - } - } else { - // try find a replacement modal dialog - Client *replacement = 0; - - Client *c = this; - while (c->_transient_for) // go up the tree - c = c->_transient_for; - replacement = c->findModalChild(this); // find a modal child, skipping this - - c = this; - while (c->_transient_for) { - c = c->_transient_for; - if (c->_modal_child != this) break; // has a different modal child - c->_modal_child = replacement; - } - } - _modal = modal; + if (show) frame->show(); + else frame->hide(); } @@ -850,7 +784,6 @@ void Client::setState(StateAction action, long data1, long data2) bool fsstate = _fullscreen; bool maxh = _max_horz; bool maxv = _max_vert; - bool modal = _modal; if (!(action == State_Add || action == State_Remove || action == State_Toggle)) @@ -886,7 +819,7 @@ void Client::setState(StateAction action, long data1, long data2) if (action == State_Add) { if (state == otk::Property::atoms.net_wm_state_modal) { if (_modal) continue; - modal = true; + _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) { @@ -911,7 +844,7 @@ void Client::setState(StateAction action, long data1, long data2) } else { // action == State_Remove if (state == otk::Property::atoms.net_wm_state_modal) { if (!_modal) continue; - modal = false; + _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) { @@ -948,8 +881,6 @@ void Client::setState(StateAction action, long data1, long data2) maximize(maxv, 2, true); } } - if (modal != _modal) - setModal(modal); // change fullscreen state before shading, as it will affect if the window // can shade or not if (fsstate != _fullscreen) @@ -1086,15 +1017,23 @@ void Client::clientMessageHandler(const XClientMessageEvent &e) #ifdef DEBUG printf("net_active_window for 0x%lx\n", _window); #endif + if (openbox->screen(_screen)->showingDesktop()) + openbox->screen(_screen)->showDesktop(false); if (_iconic) - setDesktop(openbox->screen(_screen)->desktop()); + 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) - setDesktop(openbox->screen(_screen)->desktop()); + 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(); @@ -1117,33 +1056,26 @@ void Client::shapeHandler(const XShapeEvent &e) #endif -void Client::resize(Corner anchor, unsigned int w, unsigned int h) +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, unsigned int w, unsigned int h, +void Client::internal_resize(Corner anchor, int w, int h, bool user, int x, int y) { - if (_base_size.width() < w) - w -= _base_size.width(); - else - w = 0; - if (_base_size.height() < h) - h -= _base_size.height(); - else - h = 0; + w -= _base_size.width(); + h -= _base_size.height(); if (user) { // for interactive resizing. have to move half an increment in each // direction. - unsigned int mw = w % _size_inc.width(); // how far we are towards the next - // size inc - unsigned int mh = h % _size_inc.height(); - unsigned int aw = _size_inc.width() / 2; // amount to add - unsigned int ah = _size_inc.height() / 2; + 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; @@ -1154,10 +1086,10 @@ void Client::internal_resize(Corner anchor, unsigned int w, unsigned int h, // 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(); - else if (w > _max_size.width()) w = _max_size.width(); + if (h > _max_size.height()) h = _max_size.height(); if (h < _min_size.height()) h = _min_size.height(); - else if (h > _max_size.height()) h = _max_size.height(); // adjust the height ot match the width for the aspect ratios if (_min_ratio) @@ -1387,14 +1319,9 @@ void Client::applyStartupState() { // these are in a carefully crafted order.. - if (_modal) { - _modal = false; - setModal(true); - } - if (_iconic) { _iconic = false; - setDesktop(ICONIC_DESKTOP); + iconify(true); } if (_fullscreen) { _fullscreen = false; @@ -1464,7 +1391,7 @@ void Client::maximize(bool max, int dir, bool savearea) if (dir == 2 && !_max_vert) return; } - const otk::Rect &a = openbox->screen(_screen)->area(); + const otk::Rect &a = openbox->screen(_screen)->area(_desktop); int x = frame->area().x(), y = frame->area().y(), w = _area.width(), h = _area.height(); @@ -1609,7 +1536,7 @@ void Client::fullscreen(bool fs, bool savearea) delete dimensions; } else { // pick some fallbacks... - const otk::Rect &a = openbox->screen(_screen)->area(); + 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; @@ -1630,6 +1557,36 @@ void Client::fullscreen(bool fs, bool savearea) } +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; @@ -1649,11 +1606,32 @@ void Client::installColormap(bool install) const } +// 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) +{ + 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 - if (_modal_child) - return _modal_child->focus(); + 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 @@ -1901,7 +1879,7 @@ void Client::mapRequestHandler(const XMapRequestEvent &e) assert(_iconic); // we shouldn't be able to get this unless we're iconic // move to the current desktop (uniconify) - setDesktop(openbox->screen(_screen)->desktop()); + iconify(false); // XXX: should we focus/raise the window? (basically a net_wm_active_window) }