X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=util%2Fepist%2Fwindow.cc;h=7ee674268551c8e3d8598bc66a2f717472967d1c;hb=6595476d81f01cee9001bbc90dda5b37915e5821;hp=4027b47fb337def6cd6b3d767ee25cd273f26ee1;hpb=a0e50e15b507f1f8752bd7858c9e758265a34fc4;p=chaz%2Fopenbox diff --git a/util/epist/window.cc b/util/epist/window.cc index 4027b47f..7ee67426 100644 --- a/util/epist/window.cc +++ b/util/epist/window.cc @@ -31,17 +31,21 @@ using std::endl; using std::hex; using std::dec; -#include "window.hh" #include "epist.hh" +#include "screen.hh" +#include "window.hh" #include "../../src/XAtom.hh" -XWindow::XWindow(epist *epist, Window window) - : _epist(epist), _xatom(epist->xatom()), _window(window) { +XWindow::XWindow(epist *epist, screen *screen, Window window) + : _epist(epist), _screen(screen), _xatom(epist->xatom()), _window(window) { _unmapped = false; XSelectInput(_epist->getXDisplay(), _window, PropertyChangeMask | StructureNotifyMask); + + updateDimentions(); + updateGravity(); updateState(); updateDesktop(); updateTitle(); @@ -58,6 +62,33 @@ XWindow::~XWindow() { } +void XWindow::updateDimentions() { + Window root, child; + int x, y; + unsigned int w, h, b, d; + + if (XGetGeometry(_epist->getXDisplay(), _window, &root, &x, &y, &w, &h, + &b, &d) && + XTranslateCoordinates(_epist->getXDisplay(), _window, root, x, y, + &x, &y, &child)) + _rect.setRect(x, y, w, h); + else + _rect.setRect(0, 0, 1, 1); +} + + +void XWindow::updateGravity() { + XSizeHints size; + long ret; + + if (XGetWMNormalHints(_epist->getXDisplay(), _window, &size, &ret) && + (size.flags & PWinGravity)) + _gravity = size.win_gravity; + else + _gravity = NorthWestGravity; +} + + void XWindow::updateState() { // set the defaults _shaded = _iconic = _max_vert = _max_horz = false; @@ -122,9 +153,13 @@ void XWindow::processEvent(const XEvent &e) { assert(e.xany.window == _window); switch (e.type) { + case ConfigureNotify: + updateDimentions(); + break; case PropertyNotify: - // a client window - if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state)) + if (e.xproperty.atom == XA_WM_NORMAL_HINTS) + updateGravity(); + else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state)) updateState(); else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_desktop)) updateDesktop(); @@ -140,3 +175,203 @@ void XWindow::processEvent(const XEvent &e) { break; } } + + +void XWindow::shade(const bool sh) const { + _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state, + _window, (sh ? 1 : 0), + _xatom->getAtom(XAtom::net_wm_state_shaded)); +} + + +void XWindow::close() const { + _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_close_window, + _window); +} + + +void XWindow::raise() const { + XRaiseWindow(_epist->getXDisplay(), _window); +} + + +void XWindow::lower() const { + XLowerWindow(_epist->getXDisplay(), _window); +} + + +void XWindow::iconify() const { + _xatom->sendClientMessage(_screen->rootWindow(), XAtom::wm_change_state, + _window, IconicState); +} + + +void XWindow::focus() const { + // this will also unshade the window.. + _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_active_window, + _window); +} + + +void XWindow::sendTo(unsigned int dest) const { + _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_desktop, + _window, dest); +} + + +void XWindow::move(int x, int y) const { + // get the window's decoration sizes (margins) + Strut margins; + Window win = _window, parent, root, last = None; + Window *children = 0; + unsigned int nchildren; + XWindowAttributes wattr; + + while (XQueryTree(_epist->getXDisplay(), win, &root, &parent, &children, + &nchildren)) { + if (children && nchildren > 0) + XFree(children); // don't care about the children + + if (! parent) // no parent!? + return; + + // if the parent window is the root window, stop here + if (parent == root) + break; + + last = win; + win = parent; + } + + if (! (XTranslateCoordinates(_epist->getXDisplay(), last, win, 0, 0, + (int *) &margins.left, + (int *) &margins.top, + &parent) && + XGetWindowAttributes(_epist->getXDisplay(), win, &wattr))) + return; + + margins.right = wattr.width - _rect.width() - margins.left; + margins.bottom = wattr.height - _rect.height() - margins.top; + + margins.left += wattr.border_width; + margins.right += wattr.border_width; + margins.top += wattr.border_width; + margins.bottom += wattr.border_width; + + // this makes things work. why? i don't know. but you need them. + margins.right -= 2; + margins.bottom -= 2; + + // find the frame's reference position based on the window's gravity + switch (_gravity) { + case NorthWestGravity: + x -= margins.left; + y -= margins.top; + break; + case NorthGravity: + x += (margins.left + margins.right) / 2; + y -= margins.top; + break; + case NorthEastGravity: + x += margins.right; + y -= margins.top; + case WestGravity: + x -= margins.left; + y += (margins.top + margins.bottom) / 2; + break; + case CenterGravity: + x += (margins.left + margins.right) / 2; + y += (margins.top + margins.bottom) / 2; + break; + case EastGravity: + x += margins.right; + y += (margins.top + margins.bottom) / 2; + case SouthWestGravity: + x -= margins.left; + y += margins.bottom; + break; + case SouthGravity: + x += (margins.left + margins.right) / 2; + y += margins.bottom; + break; + case SouthEastGravity: + x += margins.right; + y += margins.bottom; + break; + default: + break; + } + + XMoveWindow(_epist->getXDisplay(), _window, x, y); +} + + +void XWindow::resize(unsigned int width, unsigned int height) const { + XResizeWindow(_epist->getXDisplay(), _window, width, height); +} + + +void XWindow::toggleMaximize(Max max) const { + switch (max) { + case Max_Full: + _xatom-> + sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state, + _window, (_max_vert == _max_horz ? 2 : 1), + _xatom->getAtom(XAtom::net_wm_state_maximized_horz), + _xatom->getAtom(XAtom::net_wm_state_maximized_vert)); + break; + + case Max_Horz: + _xatom-> + sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state, + _window, 2, + _xatom->getAtom(XAtom::net_wm_state_maximized_horz)); + break; + + case Max_Vert: + _xatom-> + sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state, + _window, 2, + _xatom->getAtom(XAtom::net_wm_state_maximized_vert)); + break; + + case Max_None: + assert(false); // you should not do this. it is pointless and probly a bug + break; + } +} + + +void XWindow::maximize(Max max) const { + switch (max) { + case Max_None: + _xatom-> + sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state, + _window, 0, + _xatom->getAtom(XAtom::net_wm_state_maximized_horz), + _xatom->getAtom(XAtom::net_wm_state_maximized_vert)); + break; + + case Max_Full: + _xatom-> + sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state, + _window, 1, + _xatom->getAtom(XAtom::net_wm_state_maximized_horz), + _xatom->getAtom(XAtom::net_wm_state_maximized_vert)); + break; + + case Max_Horz: + _xatom-> + sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state, + _window, 1, + _xatom->getAtom(XAtom::net_wm_state_maximized_horz)); + break; + + case Max_Vert: + _xatom-> + sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state, + _window, 1, + _xatom->getAtom(XAtom::net_wm_state_maximized_vert)); + break; + } +}