OBClient::OBClient(int screen, Window window)
: otk::OtkEventHandler(),
- _screen(screen), _window(window)
+ frame(0), _screen(screen), _window(window)
{
assert(screen >= 0);
assert(window);
{
XSizeHints size;
long ret;
+ int oldgravity = _gravity;
// defaults
_gravity = NorthWestGravity;
if (size.flags & PWinGravity)
_gravity = size.win_gravity;
-
+
if (size.flags & PMinSize)
_min_size.setPoint(size.min_width, size.min_height);
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);
+ }
}
}
+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);
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);
}
{
_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)
// 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
*/
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; }
if (replace) {
// XXX: do shit here whatever
- // XXX: save the position based on gravity
}
_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();
}
+void OBFrame::adjustPosition()
+{
+ int x, y;
+ clientGravity(x, y);
+ move(x, y);
+}
+
+
void OBFrame::adjustShape()
{
#ifdef SHAPE
_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();
}
}
-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;
+ }
}
*/
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
/*!
//! 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();
};
}
}
}
-
-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);
-}
-
-
}
virtual void propertyHandler(const XPropertyEvent &e);
virtual void clientMessageHandler(const XClientMessageEvent &e);
virtual void mapRequestHandler(const XMapRequestEvent &);
- virtual void configureRequestHandler(const XConfigureRequestEvent &e);
};
}
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
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;