keep track of window dimentions
use them for window moving
This commit is contained in:
parent
54dfa44cbe
commit
6595476d81
3 changed files with 154 additions and 114 deletions
|
@ -246,19 +246,27 @@ void screen::handleKeypress(const XEvent &e) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::moveWindowUp:
|
case Action::moveWindowUp:
|
||||||
window->move(0, -it->number());
|
window->move(window->x(), window->y() - it->number());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::moveWindowDown:
|
case Action::moveWindowDown:
|
||||||
window->move(0, it->number());
|
window->move(window->x(), window->y() + it->number());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::moveWindowLeft:
|
case Action::moveWindowLeft:
|
||||||
window->move(-it->number(), 0);
|
window->move(window->x() - it->number(), window->y());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::moveWindowRight:
|
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;
|
return;
|
||||||
|
|
||||||
case Action::toggleshade:
|
case Action::toggleshade:
|
||||||
|
|
|
@ -43,6 +43,9 @@ XWindow::XWindow(epist *epist, screen *screen, Window window)
|
||||||
|
|
||||||
XSelectInput(_epist->getXDisplay(), _window,
|
XSelectInput(_epist->getXDisplay(), _window,
|
||||||
PropertyChangeMask | StructureNotifyMask);
|
PropertyChangeMask | StructureNotifyMask);
|
||||||
|
|
||||||
|
updateDimentions();
|
||||||
|
updateGravity();
|
||||||
updateState();
|
updateState();
|
||||||
updateDesktop();
|
updateDesktop();
|
||||||
updateTitle();
|
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() {
|
void XWindow::updateState() {
|
||||||
// set the defaults
|
// set the defaults
|
||||||
_shaded = _iconic = _max_vert = _max_horz = false;
|
_shaded = _iconic = _max_vert = _max_horz = false;
|
||||||
|
@ -123,9 +153,13 @@ void XWindow::processEvent(const XEvent &e) {
|
||||||
assert(e.xany.window == _window);
|
assert(e.xany.window == _window);
|
||||||
|
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
|
case ConfigureNotify:
|
||||||
|
updateDimentions();
|
||||||
|
break;
|
||||||
case PropertyNotify:
|
case PropertyNotify:
|
||||||
// a client window
|
if (e.xproperty.atom == XA_WM_NORMAL_HINTS)
|
||||||
if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state))
|
updateGravity();
|
||||||
|
else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state))
|
||||||
updateState();
|
updateState();
|
||||||
else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_desktop))
|
else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_desktop))
|
||||||
updateDesktop();
|
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 {
|
void XWindow::shade(const bool sh) const {
|
||||||
_xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state,
|
_xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state,
|
||||||
_window, (sh ? 1 : 0),
|
_window, (sh ? 1 : 0),
|
||||||
|
@ -285,9 +220,94 @@ void XWindow::sendTo(unsigned int dest) const {
|
||||||
|
|
||||||
|
|
||||||
void XWindow::move(int x, int y) const {
|
void XWindow::move(int x, int y) const {
|
||||||
int fx, fy;
|
// get the window's decoration sizes (margins)
|
||||||
findFramePosition(fx, fy);
|
Strut margins;
|
||||||
XMoveWindow(_epist->getXDisplay(), _window, fx + x, fy + y);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,13 +30,12 @@ extern "C" {
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "../../src/Util.hh"
|
||||||
|
|
||||||
class epist;
|
class epist;
|
||||||
class screen;
|
class screen;
|
||||||
class XWindow;
|
|
||||||
class XAtom;
|
class XAtom;
|
||||||
|
|
||||||
typedef std::list<XWindow *> WindowList;
|
|
||||||
|
|
||||||
class XWindow {
|
class XWindow {
|
||||||
public:
|
public:
|
||||||
enum Max {
|
enum Max {
|
||||||
|
@ -47,15 +46,18 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
epist *_epist;
|
epist *_epist;
|
||||||
screen *_screen;
|
screen *_screen;
|
||||||
XAtom *_xatom;
|
XAtom *_xatom;
|
||||||
|
|
||||||
Window _window;
|
Window _window;
|
||||||
|
|
||||||
unsigned int _desktop;
|
unsigned int _desktop;
|
||||||
std::string _title;
|
std::string _title;
|
||||||
std::string _app_name;
|
std::string _app_name;
|
||||||
std::string _app_class;
|
std::string _app_class;
|
||||||
|
Rect _rect;
|
||||||
|
int _gravity;
|
||||||
|
|
||||||
// states
|
// states
|
||||||
bool _shaded;
|
bool _shaded;
|
||||||
|
@ -65,6 +67,8 @@ private:
|
||||||
|
|
||||||
bool _unmapped;
|
bool _unmapped;
|
||||||
|
|
||||||
|
void updateDimentions();
|
||||||
|
void updateGravity();
|
||||||
void updateState();
|
void updateState();
|
||||||
void updateDesktop();
|
void updateDesktop();
|
||||||
void updateTitle();
|
void updateTitle();
|
||||||
|
@ -87,6 +91,11 @@ public:
|
||||||
inline bool iconic() const { return _iconic; }
|
inline bool iconic() const { return _iconic; }
|
||||||
inline bool maxVert() const { return _max_vert; }
|
inline bool maxVert() const { return _max_vert; }
|
||||||
inline bool maxHorz() const { return _max_horz; }
|
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);
|
void processEvent(const XEvent &e);
|
||||||
|
|
||||||
|
@ -98,6 +107,7 @@ public:
|
||||||
void focus() const;
|
void focus() const;
|
||||||
void sendTo(unsigned int dest) const;
|
void sendTo(unsigned int dest) const;
|
||||||
void move(int x, int y) 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 toggleMaximize(Max max) const; // i hate toggle functions
|
||||||
void maximize(Max max) const;
|
void maximize(Max max) const;
|
||||||
|
|
||||||
|
@ -105,4 +115,6 @@ public:
|
||||||
bool operator == (const Window &w) const { return w == _window; }
|
bool operator == (const Window &w) const { return w == _window; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::list<XWindow *> WindowList;
|
||||||
|
|
||||||
#endif // __window_hh
|
#endif // __window_hh
|
||||||
|
|
Loading…
Reference in a new issue