From 52cb7bd11ed83a57c4c1affcdac8a1f7d68ae551 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Thu, 5 Dec 2002 13:45:00 +0000 Subject: [PATCH] PROPERLY HANDLE CLIENT BORDERS PROPERLY HANDLE CLIENT GRAVITY YES!#%&*#!#! windows can be moved/resized now (and the frame will play along)! --- src/client.cc | 86 +++++++++++++++++++++++++++++++++----- src/client.hh | 13 +++--- src/frame.cc | 104 +++++++++++++++++++++++++++++++++++----------- src/frame.hh | 30 ++++++++----- src/rootwindow.cc | 21 ---------- src/rootwindow.hh | 1 - src/screen.cc | 9 ++-- 7 files changed, 186 insertions(+), 78 deletions(-) diff --git a/src/client.cc b/src/client.cc index aef3dcba..07d75462 100644 --- a/src/client.cc +++ b/src/client.cc @@ -26,7 +26,7 @@ namespace ob { OBClient::OBClient(int screen, Window window) : otk::OtkEventHandler(), - _screen(screen), _window(window) + frame(0), _screen(screen), _window(window) { assert(screen >= 0); assert(window); @@ -371,6 +371,7 @@ void OBClient::updateNormalHints() { XSizeHints size; long ret; + int oldgravity = _gravity; // defaults _gravity = NorthWestGravity; @@ -388,7 +389,7 @@ void OBClient::updateNormalHints() if (size.flags & PWinGravity) _gravity = size.win_gravity; - + if (size.flags & PMinSize) _min_size.setPoint(size.min_width, size.min_height); @@ -401,6 +402,15 @@ void OBClient::updateNormalHints() if (size.flags & PResizeInc) _size_inc.setPoint(size.width_inc, size.height_inc); } + + // 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, y; + frame->frameGravity(x, y); + _area.setPos(x, y); + } } @@ -651,6 +661,57 @@ void OBClient::setState(StateAction action, long data1, long data2) } +void OBClient::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 x = _area.x(), y = _area.y(); + switch(_gravity) { + case NorthWestGravity: + case WestGravity: + case SouthWestGravity: + if (addborder) x += _border_width; + else x -= _border_width; + break; + case NorthEastGravity: + case EastGravity: + case SouthEastGravity: + if (addborder) x -= _border_width * 2; + else x += _border_width * 2; + break; + } + switch(_gravity) { + case NorthWestGravity: + case NorthGravity: + case NorthEastGravity: + if (addborder) y += _border_width; + else y -= _border_width; + break; + case SouthWestGravity: + case SouthGravity: + case SouthEastGravity: + if (addborder) y -= _border_width * 2; + else y += _border_width * 2; + break; + default: + // no change for StaticGravity etc. + break; + } + _area.setPos(x, y); + + if (addborder) { + XSetWindowBorderWidth(otk::OBDisplay::display, _window, _border_width); + + // move the client so it is back it the right spot _with_ its border! + XMoveWindow(otk::OBDisplay::display, _window, x, y); + } else + XSetWindowBorderWidth(otk::OBDisplay::display, _window, 0); +} + + void OBClient::clientMessageHandler(const XClientMessageEvent &e) { otk::OtkEventHandler::clientMessageHandler(e); @@ -738,26 +799,29 @@ void OBClient::resize(Corner anchor, int w, int h) w += _base_size.x(); h += _base_size.y(); - + + int x = _area.x(), y = _area.y(); switch (anchor) { case TopLeft: break; case TopRight: - _area.setX(_area.x() - _area.width() - w); + x -= w - _area.width(); break; case BottomLeft: - _area.setY(_area.y() - _area.height() - h); + y -= h - _area.height(); break; case BottomRight: - _area.setX(_area.x() - _area.width() - w); - _area.setY(_area.y() - _area.height() - h); + x -= w - _area.width(); + y -= h - _area.height(); break; } _area.setSize(w, h); + XResizeWindow(otk::OBDisplay::display, _window, w, h); - // resize the frame to match - frame->adjust(); + // resize the frame to match the request + frame->adjustSize(); + move(x, y); } @@ -765,14 +829,14 @@ void OBClient::move(int x, int y) { _area.setPos(x, y); // move the frame to be in the requested position - frame->applyGravity(); + frame->adjustPosition(); } void OBClient::configureRequestHandler(const XConfigureRequestEvent &e) { OtkEventHandler::configureRequestHandler(e); - + // XXX: if we are iconic (or shaded? (fvwm does that)) ignore the event if (e.value_mask & CWBorderWidth) diff --git a/src/client.hh b/src/client.hh index e07ce12d..37e26cb2 100644 --- a/src/client.hh +++ b/src/client.hh @@ -297,10 +297,6 @@ private: // XXX: updateTransientFor(); //! Move the client window - /*! - This shouldnt be used to move the window internally! It will apply - window gravity after moving the window. - */ void move(int x, int y); //! Resizes the client window, anchoring it in a given corner @@ -409,8 +405,13 @@ public: */ inline bool floating() const { return _floating; } - //! Returns the client's requested border width (not used by the wm) - inline int borderWidth() const { return _border_width; } + //! 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); //! Returns the position and size of the client relative to the root window inline const otk::Rect &area() const { return _area; } diff --git a/src/frame.cc b/src/frame.cc index aa1e868f..15404f93 100644 --- a/src/frame.cc +++ b/src/frame.cc @@ -104,7 +104,6 @@ void OBFrame::setStyle(otk::Style *style) if (replace) { // XXX: do shit here whatever - // XXX: save the position based on gravity } _style = style; @@ -125,12 +124,15 @@ void OBFrame::setStyle(otk::Style *style) _style->getBorderColor()->pixel()); // if !replace, then adjust() will get called after the client is grabbed! - if (replace) - adjust(); // size/position everything + if (replace) { + // size/position everything + adjustSize(); + adjustPosition(); + } } -void OBFrame::adjust() +void OBFrame::adjustSize() { // XXX: only if not overridden or something!!! MORE LOGIC HERE!! _decorations = _client->decorations(); @@ -311,6 +313,14 @@ void OBFrame::adjust() } +void OBFrame::adjustPosition() +{ + int x, y; + clientGravity(x, y); + move(x, y); +} + + void OBFrame::adjustShape() { #ifdef SHAPE @@ -365,15 +375,15 @@ void OBFrame::grabClient() _plate.getWindow(), 0, 0); _client->ignore_unmaps++; - // select the event mask on the client's parent - //XSelectInput(otk::OBDisplay::display, _plate.getWindow(), - // SubstructureRedirectMask); + // select the event mask on the client's parent (to receive config req's) + XSelectInput(otk::OBDisplay::display, _plate.getWindow(), + SubstructureRedirectMask); // map the client so it maps when the frame does XMapWindow(otk::OBDisplay::display, _client->window()); - adjust(); - applyGravity(); + adjustSize(); + adjustPosition(); } @@ -399,69 +409,115 @@ void OBFrame::releaseClient(bool remap) } -void OBFrame::applyGravity() +void OBFrame::clientGravity(int &x, int &y) { - int x, y; - // apply horizontal window gravity + x = _client->area().x(); + y = _client->area().y(); + + // horizontal switch (_client->gravity()) { default: case NorthWestGravity: case SouthWestGravity: case WestGravity: - x = _client->area().x(); break; case NorthGravity: case SouthGravity: case CenterGravity: - x = _client->area().x() - (_size.left + _size.right) / 2; + x -= (_size.left + _size.right) / 2; break; case NorthEastGravity: case SouthEastGravity: case EastGravity: - x = _client->area().x() - _size.left - _size.right + 2; + x -= _size.left + _size.right; break; case ForgetGravity: case StaticGravity: - x = _client->area().x() - _size.left; + x -= _size.left; break; } - // apply vertical window gravity + // vertical switch (_client->gravity()) { default: case NorthWestGravity: case NorthEastGravity: case NorthGravity: - y = _client->area().y(); break; case CenterGravity: case EastGravity: case WestGravity: - y = _client->area().y() - (_size.top + _size.bottom) / 2; + y -= (_size.top + _size.bottom) / 2; break; case SouthWestGravity: case SouthEastGravity: case SouthGravity: - y = _client->area().y() - _size.top - _size.bottom + 2; + y -= _size.top + _size.bottom; break; case ForgetGravity: case StaticGravity: - y = _client->area().y() - _size.top; + y -= _size.top; break; } - move(x, y); } -void OBFrame::reverseGravity() +void OBFrame::frameGravity(int &x, int &y) { - move(_client->area().x() - _size.left, _client->area().y() - _size.top); + x = getRect().x(); + y = getRect().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 index 1816ad01..7248c71f 100644 --- a/src/frame.hh +++ b/src/frame.hh @@ -75,6 +75,9 @@ private: */ void releaseClient(bool remap); + //! Shape the frame window to the client window + void adjustShape(); + public: //! Constructs an OBFrame object, and reparents the client to itself /*! @@ -88,18 +91,25 @@ public: //! Set the style to decorate the frame with virtual void setStyle(otk::Style *style); - //! Update the frame to match the client - void adjust(); - //! Shape the frame window to the client window - void adjustShape(); + //! Update the frame's size to match the client + void adjustSize(); + //! Update the frame's position to match the client + void adjustPosition(); - //! Applies gravity for the client's gravity, moving the frame to the - //! appropriate place - void applyGravity(); + //! 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); - //! Reversely applies gravity for the client's gravity, moving the frame so - //! that the client is in its pre-gravity position - void reverseGravity(); }; } diff --git a/src/rootwindow.cc b/src/rootwindow.cc index 23361761..3fccc44a 100644 --- a/src/rootwindow.cc +++ b/src/rootwindow.cc @@ -108,25 +108,4 @@ void OBRootWindow::mapRequestHandler(const XMapRequestEvent &e) } } - -void OBRootWindow::configureRequestHandler(const XConfigureRequestEvent &e) -{ - OtkEventHandler::configureRequestHandler(e); - - // when configure requests come to the root window, just pass them on - XWindowChanges xwc; - - xwc.x = e.x; - xwc.y = e.y; - xwc.width = e.width; - xwc.height = e.height; - xwc.border_width = e.border_width; - xwc.sibling = e.above; - xwc.stack_mode = e.detail; - - XConfigureWindow(otk::OBDisplay::display, e.window, - e.value_mask, &xwc); -} - - } diff --git a/src/rootwindow.hh b/src/rootwindow.hh index 35cda699..d78f4ff7 100644 --- a/src/rootwindow.hh +++ b/src/rootwindow.hh @@ -62,7 +62,6 @@ public: virtual void propertyHandler(const XPropertyEvent &e); virtual void clientMessageHandler(const XClientMessageEvent &e); virtual void mapRequestHandler(const XMapRequestEvent &); - virtual void configureRequestHandler(const XConfigureRequestEvent &e); }; } diff --git a/src/screen.cc b/src/screen.cc index 22d5d1be..d40a2a3a 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -354,7 +354,7 @@ void OBScreen::manageWindow(Window window) Openbox::instance->registerHandler(window, client); // we dont want a border on the client - XSetWindowBorderWidth(otk::OBDisplay::display, window, 0); + client->toggleClientBorder(false); // specify that if we exit, the window should not be destroyed and should be // reparented back to root automatically @@ -399,10 +399,9 @@ void OBScreen::unmanageWindow(OBClient *client) XSelectInput(otk::OBDisplay::display, client->window(), NoEventMask); frame->hide(); - - // we dont want a border on the client - XSetWindowBorderWidth(otk::OBDisplay::display, client->window(), - client->borderWidth()); + + // give the client its border back + client->toggleClientBorder(true); delete client->frame; client->frame = 0; -- 2.44.0