keep track of window dimentions

use them for window moving
This commit is contained in:
Dana Jansens 2002-07-20 20:04:27 +00:00
parent 54dfa44cbe
commit 6595476d81
3 changed files with 154 additions and 114 deletions

View file

@ -246,19 +246,27 @@ void screen::handleKeypress(const XEvent &e) {
return;
case Action::moveWindowUp:
window->move(0, -it->number());
window->move(window->x(), window->y() - it->number());
return;
case Action::moveWindowDown:
window->move(0, it->number());
window->move(window->x(), window->y() + it->number());
return;
case Action::moveWindowLeft:
window->move(-it->number(), 0);
window->move(window->x() - it->number(), window->y());
return;
case Action::moveWindowRight:
window->move(it->number(), 0);
window->move(window->x() + it->number(), window->y());
return;
case Action::resizeWindowWidth:
window->resize(window->width() + it->number(), window->height());
return;
case Action::resizeWindowHeight:
window->resize(window->width(), window->height() + it->number());
return;
case Action::toggleshade:

View file

@ -43,6 +43,9 @@ XWindow::XWindow(epist *epist, screen *screen, Window window)
XSelectInput(_epist->getXDisplay(), _window,
PropertyChangeMask | StructureNotifyMask);
updateDimentions();
updateGravity();
updateState();
updateDesktop();
updateTitle();
@ -59,6 +62,33 @@ 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::updateGravity() {
XSizeHints size;
long ret;
if (XGetWMNormalHints(_epist->getXDisplay(), _window, &size, &ret) &&
(size.flags & PWinGravity))
_gravity = size.win_gravity;
else
_gravity = NorthWestGravity;
}
void XWindow::updateState() {
// set the defaults
_shaded = _iconic = _max_vert = _max_horz = false;
@ -123,9 +153,13 @@ 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)
updateGravity();
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,105 +177,6 @@ void XWindow::processEvent(const XEvent &e) {
}
void XWindow::findFramePosition(int &x, int &y) const {
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)
XFree(children); // don't care about the children
if (! parent) // no parent!?
return;
// if the parent window is the root window, stop here
if (parent == root)
break;
last = win;
win = parent;
}
if (! (XTranslateCoordinates(_epist->getXDisplay(), last, win, 0, 0,
&left, &top, &parent) &&
XGetWindowAttributes(_epist->getXDisplay(), win, &wattr)))
return;
right = wattr.width - cwidth - left;
bottom = wattr.height - cheight - 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;
// this makes things work. why? i don't know. but you need them.
right -= 2;
bottom -= 2;
// find the frame's reference position based on the window's gravity
switch (gravity) {
case NorthWestGravity:
x -= left;
y -= top;
break;
case NorthGravity:
x += (left + right) / 2;
y -= top;
break;
case NorthEastGravity:
x += right;
y -= top;
case WestGravity:
x -= left;
y += (top + bottom) / 2;
break;
case CenterGravity:
x += (left + right) / 2;
y += (top + bottom) / 2;
break;
case EastGravity:
x += right;
y += (top + bottom) / 2;
case SouthWestGravity:
x -= left;
y += bottom;
break;
case SouthGravity:
x += (left + right) / 2;
y += bottom;
break;
case SouthEastGravity:
x += right;
y += bottom;
break;
default:
break;
}
}
void XWindow::shade(const bool sh) const {
_xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state,
_window, (sh ? 1 : 0),
@ -285,9 +220,94 @@ void XWindow::sendTo(unsigned int dest) const {
void XWindow::move(int x, int y) const {
int fx, fy;
findFramePosition(fx, fy);
XMoveWindow(_epist->getXDisplay(), _window, fx + x, fy + y);
// get the window's decoration sizes (margins)
Strut margins;
Window win = _window, parent, root, last = None;
Window *children = 0;
unsigned int nchildren;
XWindowAttributes wattr;
while (XQueryTree(_epist->getXDisplay(), win, &root, &parent, &children,
&nchildren)) {
if (children && nchildren > 0)
XFree(children); // don't care about the children
if (! parent) // no parent!?
return;
// if the parent window is the root window, stop here
if (parent == root)
break;
last = win;
win = parent;
}
if (! (XTranslateCoordinates(_epist->getXDisplay(), last, win, 0, 0,
(int *) &margins.left,
(int *) &margins.top,
&parent) &&
XGetWindowAttributes(_epist->getXDisplay(), win, &wattr)))
return;
margins.right = wattr.width - _rect.width() - margins.left;
margins.bottom = wattr.height - _rect.height() - margins.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.
margins.right -= 2;
margins.bottom -= 2;
// find the frame's reference position based on the window's gravity
switch (_gravity) {
case NorthWestGravity:
x -= margins.left;
y -= margins.top;
break;
case NorthGravity:
x += (margins.left + margins.right) / 2;
y -= margins.top;
break;
case NorthEastGravity:
x += margins.right;
y -= margins.top;
case WestGravity:
x -= margins.left;
y += (margins.top + margins.bottom) / 2;
break;
case CenterGravity:
x += (margins.left + margins.right) / 2;
y += (margins.top + margins.bottom) / 2;
break;
case EastGravity:
x += margins.right;
y += (margins.top + margins.bottom) / 2;
case SouthWestGravity:
x -= margins.left;
y += margins.bottom;
break;
case SouthGravity:
x += (margins.left + margins.right) / 2;
y += margins.bottom;
break;
case SouthEastGravity:
x += margins.right;
y += margins.bottom;
break;
default:
break;
}
XMoveWindow(_epist->getXDisplay(), _window, x, y);
}
void XWindow::resize(unsigned int width, unsigned int height) const {
XResizeWindow(_epist->getXDisplay(), _window, width, height);
}

View file

@ -30,13 +30,12 @@ extern "C" {
#include <list>
#include <string>
#include "../../src/Util.hh"
class epist;
class screen;
class XWindow;
class XAtom;
typedef std::list<XWindow *> WindowList;
class XWindow {
public:
enum Max {
@ -47,15 +46,18 @@ public:
};
private:
epist *_epist;
epist *_epist;
screen *_screen;
XAtom *_xatom;
XAtom *_xatom;
Window _window;
unsigned int _desktop;
std::string _title;
std::string _app_name;
std::string _app_class;
Rect _rect;
int _gravity;
// states
bool _shaded;
@ -65,6 +67,8 @@ private:
bool _unmapped;
void updateDimentions();
void updateGravity();
void updateState();
void updateDesktop();
void updateTitle();
@ -87,6 +91,11 @@ public:
inline bool iconic() const { return _iconic; }
inline bool maxVert() const { return _max_vert; }
inline bool maxHorz() const { return _max_horz; }
inline const Rect &area() const { return _rect; }
inline unsigned int x() const { return _rect.x(); }
inline unsigned int y() const { return _rect.y(); }
inline unsigned int width() const { return _rect.width(); }
inline unsigned int height() const { return _rect.height(); }
void processEvent(const XEvent &e);
@ -98,6 +107,7 @@ public:
void focus() const;
void sendTo(unsigned int dest) const;
void move(int x, int y) const;
void resize(unsigned int width, unsigned int height) const;
void toggleMaximize(Max max) const; // i hate toggle functions
void maximize(Max max) const;
@ -105,4 +115,6 @@ public:
bool operator == (const Window &w) const { return w == _window; }
};
typedef std::list<XWindow *> WindowList;
#endif // __window_hh