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:
parent
1cfc76577d
commit
52cb7bd11e
7 changed files with 186 additions and 78 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
112
src/frame.cc
112
src/frame.cc
|
@ -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;
|
|
||||||
// apply horizontal window gravity
|
|
||||||
switch (_client->gravity()) {
|
|
||||||
default:
|
|
||||||
case NorthWestGravity:
|
|
||||||
case SouthWestGravity:
|
|
||||||
case WestGravity:
|
|
||||||
x = _client->area().x();
|
x = _client->area().x();
|
||||||
|
y = _client->area().y();
|
||||||
|
|
||||||
|
// horizontal
|
||||||
|
switch (_client->gravity()) {
|
||||||
|
default:
|
||||||
|
case NorthWestGravity:
|
||||||
|
case SouthWestGravity:
|
||||||
|
case WestGravity:
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
30
src/frame.hh
30
src/frame.hh
|
@ -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();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue