X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=util%2Fepist%2Fwindow.cc;h=c8cdf012a4cca4d5e82b3c82302045a2571a4428;hb=d8967bd534ff10a234fed17059fb92d985be9176;hp=fd951aa1db9e5abe31e13bb72931f464e1388076;hpb=f7a41999bfa20750f192d7fa5447bb133451db76;p=chaz%2Fopenbox diff --git a/util/epist/window.cc b/util/epist/window.cc index fd951aa1..c8cdf012 100644 --- a/util/epist/window.cc +++ b/util/epist/window.cc @@ -43,6 +43,10 @@ XWindow::XWindow(epist *epist, screen *screen, Window window) XSelectInput(_epist->getXDisplay(), _window, PropertyChangeMask | StructureNotifyMask); + + updateNormalHints(); + updateWMHints(); + updateDimentions(); updateState(); updateDesktop(); updateTitle(); @@ -59,6 +63,58 @@ 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::updateNormalHints() { + XSizeHints size; + long ret; + + // defaults + _gravity = NorthWestGravity; + _inc_x = _inc_y = 1; + _base_x = _base_y = 0; + + if (XGetWMNormalHints(_epist->getXDisplay(), _window, &size, &ret)) { + if (size.flags & PWinGravity) + _gravity = size.win_gravity; + if (size.flags & PBaseSize) { + _base_x = size.base_width; + _base_y = size.base_height; + } + if (size.flags & PResizeInc) { + _inc_x = size.width_inc; + _inc_y = size.height_inc; + } + } +} + + +void XWindow::updateWMHints() { + XWMHints *hints; + + if ((hints = XGetWMHints(_epist->getXDisplay(), _window)) != NULL) { + _can_focus = hints->input; + XFree(hints); + } else { + // assume a window takes input if it doesnt specify + _can_focus = True; + } +} + + void XWindow::updateState() { // set the defaults _shaded = _iconic = _max_vert = _max_horz = false; @@ -123,9 +179,15 @@ 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) + updateNormalHints(); + if (e.xproperty.atom == XA_WM_HINTS) + updateWMHints(); + else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state)) updateState(); else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_desktop)) updateDesktop(); @@ -143,26 +205,58 @@ void XWindow::processEvent(const XEvent &e) { } -void XWindow::findFramePosition(int &x, int &y) const { +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 cause the window to be uniconified also + _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_active_window, + _window); + + //XSetInputFocus(_epist->getXDisplay(), _window, None, CurrentTime); +} + + +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; - int gravity, top, bottom, left, right; XWindowAttributes wattr; - XSizeHints size; - long ret; - unsigned int cwidth, cheight; - // get the location, size and gravity of the client window - if (! XGetWindowAttributes(_epist->getXDisplay(), _window, &wattr)) return; - cwidth = wattr.width; - cheight = wattr.height; - if (! XGetWMNormalHints(_epist->getXDisplay(), _window, &size, &ret)) return; - if (size.flags & PWinGravity) - gravity = size.win_gravity; - else - gravity = NorthWestGravity; - while (XQueryTree(_epist->getXDisplay(), win, &root, &parent, &children, &nchildren)) { if (children && nchildren > 0) @@ -180,112 +274,181 @@ void XWindow::findFramePosition(int &x, int &y) const { } if (! (XTranslateCoordinates(_epist->getXDisplay(), last, win, 0, 0, - &left, &top, &parent) && + (int *) &margins.left, + (int *) &margins.top, + &parent) && XGetWindowAttributes(_epist->getXDisplay(), win, &wattr))) return; - right = wattr.width - cwidth - left; - bottom = wattr.height - cheight - top; + margins.right = wattr.width - _rect.width() - margins.left; + margins.bottom = wattr.height - _rect.height() - margins.top; - left += wattr.border_width; - right += wattr.border_width; - top += wattr.border_width; - bottom += wattr.border_width; - - // find the client's location - x = wattr.x + left; - y = wattr.y + 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. - right -= 2; - bottom -= 2; - + margins.right -= 2; + margins.bottom -= 2; + // find the frame's reference position based on the window's gravity - switch (gravity) { + switch (_gravity) { case NorthWestGravity: - x -= left; - y -= top; + x -= margins.left; + y -= margins.top; break; case NorthGravity: - x += (left + right) / 2; - y -= top; + x += (margins.left + margins.right) / 2; + y -= margins.top; break; case NorthEastGravity: - x += right; - y -= top; + x += margins.right; + y -= margins.top; case WestGravity: - x -= left; - y += (top + bottom) / 2; + x -= margins.left; + y += (margins.top + margins.bottom) / 2; break; case CenterGravity: - x += (left + right) / 2; - y += (top + bottom) / 2; + x += (margins.left + margins.right) / 2; + y += (margins.top + margins.bottom) / 2; break; case EastGravity: - x += right; - y += (top + bottom) / 2; + x += margins.right; + y += (margins.top + margins.bottom) / 2; case SouthWestGravity: - x -= left; - y += bottom; + x -= margins.left; + y += margins.bottom; break; case SouthGravity: - x += (left + right) / 2; - y += bottom; + x += (margins.left + margins.right) / 2; + y += margins.bottom; break; case SouthEastGravity: - x += right; - y += bottom; + x += margins.right; + y += margins.bottom; break; default: break; } + + XMoveWindow(_epist->getXDisplay(), _window, x, y); } -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::resize(int dwidth, int dheight) const { + // resize in increments if requested by the window + unsigned int wdest = _rect.width() + (dwidth * _inc_x) / + _inc_x * _inc_x + _base_x; + unsigned int hdest = _rect.height() + (dheight * _inc_y) / + _inc_y * _inc_y + _base_y; -void XWindow::close() const { - _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_close_window, - _window); + if (width > wdest) { + while (width > wdest) + wdest += _inc_x; + } else { + while (width < wdest) + wdest -= _inc_x; + } + if (height > hdest) { + while (height > hdest) + hdest += _inc_y; + } else { + while (height < hdest) + hdest -= _inc_y; + } + + XResizeWindow(_epist->getXDisplay(), _window, wdest, hdest); } -void XWindow::raise() const { - XRaiseWindow(_epist->getXDisplay(), _window); -} +void XWindow::resize(unsigned int width, unsigned int height) const { + // resize in increments if requested by the window + unsigned int wdest = width / _inc_x * _inc_x + _base_x; + unsigned int hdest = height / _inc_y * _inc_y + _base_y; -void XWindow::lower() const { - XLowerWindow(_epist->getXDisplay(), _window); + if (width > wdest) { + while (width > wdest) + wdest += _inc_x; + } else { + while (width < wdest) + wdest -= _inc_x; + } + if (height > hdest) { + while (height > hdest) + hdest += _inc_y; + } else { + while (height < hdest) + hdest -= _inc_y; + } + + XResizeWindow(_epist->getXDisplay(), _window, wdest, hdest); } -void XWindow::iconify() const { - _xatom->sendClientMessage(_screen->rootWindow(), XAtom::wm_change_state, - _window, IconicState); -} +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; -void XWindow::focus() const { - // this will also unshade the window.. - _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_active_window, - _window); + 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::sendTo(unsigned int dest) const { - _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_desktop, - _window, dest); -} +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; -void XWindow::move(int x, int y) const { - int fx, fy; - findFramePosition(fx, fy); - XMoveWindow(_epist->getXDisplay(), _window, fx + x, fy + y); + 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; + } }