PROPERLY HANDLE CLIENT BORDERS

PROPERLY HANDLE CLIENT GRAVITY
YES!#%&*#!#!
windows can be moved/resized now (and the frame will play along)!
This commit is contained in:
Dana Jansens 2002-12-05 13:45:00 +00:00
parent 1cfc76577d
commit 52cb7bd11e
7 changed files with 186 additions and 78 deletions

View file

@ -26,7 +26,7 @@ namespace ob {
OBClient::OBClient(int screen, Window window) OBClient::OBClient(int screen, Window window)
: otk::OtkEventHandler(), : otk::OtkEventHandler(),
_screen(screen), _window(window) frame(0), _screen(screen), _window(window)
{ {
assert(screen >= 0); assert(screen >= 0);
assert(window); assert(window);
@ -371,6 +371,7 @@ void OBClient::updateNormalHints()
{ {
XSizeHints size; XSizeHints size;
long ret; long ret;
int oldgravity = _gravity;
// defaults // defaults
_gravity = NorthWestGravity; _gravity = NorthWestGravity;
@ -401,6 +402,15 @@ void OBClient::updateNormalHints()
if (size.flags & PResizeInc) if (size.flags & PResizeInc)
_size_inc.setPoint(size.width_inc, size.height_inc); _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) void OBClient::clientMessageHandler(const XClientMessageEvent &e)
{ {
otk::OtkEventHandler::clientMessageHandler(e); otk::OtkEventHandler::clientMessageHandler(e);
@ -739,25 +800,28 @@ void OBClient::resize(Corner anchor, int w, int h)
w += _base_size.x(); w += _base_size.x();
h += _base_size.y(); h += _base_size.y();
int x = _area.x(), y = _area.y();
switch (anchor) { switch (anchor) {
case TopLeft: case TopLeft:
break; break;
case TopRight: case TopRight:
_area.setX(_area.x() - _area.width() - w); x -= w - _area.width();
break; break;
case BottomLeft: case BottomLeft:
_area.setY(_area.y() - _area.height() - h); y -= h - _area.height();
break; break;
case BottomRight: case BottomRight:
_area.setX(_area.x() - _area.width() - w); x -= w - _area.width();
_area.setY(_area.y() - _area.height() - h); y -= h - _area.height();
break; break;
} }
_area.setSize(w, h); _area.setSize(w, h);
XResizeWindow(otk::OBDisplay::display, _window, w, h);
// resize the frame to match // resize the frame to match the request
frame->adjust(); frame->adjustSize();
move(x, y);
} }
@ -765,7 +829,7 @@ void OBClient::move(int x, int y)
{ {
_area.setPos(x, y); _area.setPos(x, y);
// move the frame to be in the requested position // move the frame to be in the requested position
frame->applyGravity(); frame->adjustPosition();
} }

View file

@ -297,10 +297,6 @@ private:
// XXX: updateTransientFor(); // XXX: updateTransientFor();
//! Move the client window //! 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); void move(int x, int y);
//! Resizes the client window, anchoring it in a given corner //! Resizes the client window, anchoring it in a given corner
@ -409,8 +405,13 @@ public:
*/ */
inline bool floating() const { return _floating; } inline bool floating() const { return _floating; }
//! Returns the client's requested border width (not used by the wm) //! Removes or reapplies the client's border to its window
inline int borderWidth() const { return _border_width; } /*!
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 //! Returns the position and size of the client relative to the root window
inline const otk::Rect &area() const { return _area; } inline const otk::Rect &area() const { return _area; }

View file

@ -104,7 +104,6 @@ void OBFrame::setStyle(otk::Style *style)
if (replace) { if (replace) {
// XXX: do shit here whatever // XXX: do shit here whatever
// XXX: save the position based on gravity
} }
_style = style; _style = style;
@ -125,12 +124,15 @@ void OBFrame::setStyle(otk::Style *style)
_style->getBorderColor()->pixel()); _style->getBorderColor()->pixel());
// if !replace, then adjust() will get called after the client is grabbed! // if !replace, then adjust() will get called after the client is grabbed!
if (replace) if (replace) {
adjust(); // size/position everything // size/position everything
adjustSize();
adjustPosition();
}
} }
void OBFrame::adjust() void OBFrame::adjustSize()
{ {
// XXX: only if not overridden or something!!! MORE LOGIC HERE!! // XXX: only if not overridden or something!!! MORE LOGIC HERE!!
_decorations = _client->decorations(); _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() void OBFrame::adjustShape()
{ {
#ifdef SHAPE #ifdef SHAPE
@ -365,15 +375,15 @@ void OBFrame::grabClient()
_plate.getWindow(), 0, 0); _plate.getWindow(), 0, 0);
_client->ignore_unmaps++; _client->ignore_unmaps++;
// select the event mask on the client's parent // select the event mask on the client's parent (to receive config req's)
//XSelectInput(otk::OBDisplay::display, _plate.getWindow(), XSelectInput(otk::OBDisplay::display, _plate.getWindow(),
// SubstructureRedirectMask); SubstructureRedirectMask);
// map the client so it maps when the frame does // map the client so it maps when the frame does
XMapWindow(otk::OBDisplay::display, _client->window()); XMapWindow(otk::OBDisplay::display, _client->window());
adjust(); adjustSize();
applyGravity(); adjustPosition();
} }
@ -399,69 +409,115 @@ void OBFrame::releaseClient(bool remap)
} }
void OBFrame::applyGravity() void OBFrame::clientGravity(int &x, int &y)
{ {
int x, y; x = _client->area().x();
// apply horizontal window gravity y = _client->area().y();
// horizontal
switch (_client->gravity()) { switch (_client->gravity()) {
default: default:
case NorthWestGravity: case NorthWestGravity:
case SouthWestGravity: case SouthWestGravity:
case WestGravity: case WestGravity:
x = _client->area().x();
break; break;
case NorthGravity: case NorthGravity:
case SouthGravity: case SouthGravity:
case CenterGravity: case CenterGravity:
x = _client->area().x() - (_size.left + _size.right) / 2; x -= (_size.left + _size.right) / 2;
break; break;
case NorthEastGravity: case NorthEastGravity:
case SouthEastGravity: case SouthEastGravity:
case EastGravity: case EastGravity:
x = _client->area().x() - _size.left - _size.right + 2; x -= _size.left + _size.right;
break; break;
case ForgetGravity: case ForgetGravity:
case StaticGravity: case StaticGravity:
x = _client->area().x() - _size.left; x -= _size.left;
break; break;
} }
// apply vertical window gravity // vertical
switch (_client->gravity()) { switch (_client->gravity()) {
default: default:
case NorthWestGravity: case NorthWestGravity:
case NorthEastGravity: case NorthEastGravity:
case NorthGravity: case NorthGravity:
y = _client->area().y();
break; break;
case CenterGravity: case CenterGravity:
case EastGravity: case EastGravity:
case WestGravity: case WestGravity:
y = _client->area().y() - (_size.top + _size.bottom) / 2; y -= (_size.top + _size.bottom) / 2;
break; break;
case SouthWestGravity: case SouthWestGravity:
case SouthEastGravity: case SouthEastGravity:
case SouthGravity: case SouthGravity:
y = _client->area().y() - _size.top - _size.bottom + 2; y -= _size.top + _size.bottom;
break; break;
case ForgetGravity: case ForgetGravity:
case StaticGravity: case StaticGravity:
y = _client->area().y() - _size.top; y -= _size.top;
break; 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;
}
} }

View file

@ -75,6 +75,9 @@ private:
*/ */
void releaseClient(bool remap); void releaseClient(bool remap);
//! Shape the frame window to the client window
void adjustShape();
public: public:
//! Constructs an OBFrame object, and reparents the client to itself //! Constructs an OBFrame object, and reparents the client to itself
/*! /*!
@ -88,18 +91,25 @@ public:
//! Set the style to decorate the frame with //! Set the style to decorate the frame with
virtual void setStyle(otk::Style *style); virtual void setStyle(otk::Style *style);
//! Update the frame to match the client //! Update the frame's size to match the client
void adjust(); void adjustSize();
//! Shape the frame window to the client window //! Update the frame's position to match the client
void adjustShape(); void adjustPosition();
//! Applies gravity for the client's gravity, moving the frame to the //! Applies gravity to the client's position to find where the frame should
//! appropriate place //! be positioned.
void applyGravity(); /*!
@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();
}; };
} }

View file

@ -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);
}
} }

View file

@ -62,7 +62,6 @@ public:
virtual void propertyHandler(const XPropertyEvent &e); virtual void propertyHandler(const XPropertyEvent &e);
virtual void clientMessageHandler(const XClientMessageEvent &e); virtual void clientMessageHandler(const XClientMessageEvent &e);
virtual void mapRequestHandler(const XMapRequestEvent &); virtual void mapRequestHandler(const XMapRequestEvent &);
virtual void configureRequestHandler(const XConfigureRequestEvent &e);
}; };
} }

View file

@ -354,7 +354,7 @@ void OBScreen::manageWindow(Window window)
Openbox::instance->registerHandler(window, client); Openbox::instance->registerHandler(window, client);
// we dont want a border on the 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 // specify that if we exit, the window should not be destroyed and should be
// reparented back to root automatically // reparented back to root automatically
@ -400,9 +400,8 @@ void OBScreen::unmanageWindow(OBClient *client)
frame->hide(); frame->hide();
// we dont want a border on the client // give the client its border back
XSetWindowBorderWidth(otk::OBDisplay::display, client->window(), client->toggleClientBorder(true);
client->borderWidth());
delete client->frame; delete client->frame;
client->frame = 0; client->frame = 0;