// tests for window gravity

#include <iostream>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

using namespace std;

const int gravities[ 10 ] = {
    NorthWestGravity,
    NorthGravity,
    NorthEastGravity,
    WestGravity,
    CenterGravity,
    EastGravity,
    SouthWestGravity,
    SouthGravity,
    SouthEastGravity,
    StaticGravity
};

const char* const gravity_names[ 10 ] = {
    "NW", "N", "NE", "W", "C", "E", "SW", "S", "SE", "ST"
};

Display* dpy = NULL;

int get_gravity(const char* name)
{
    for (int i = 0;
            i < 10;
            ++i)
        if (strcmp(name, gravity_names[ i ]) == 0)
            return gravities[ i ];
    cerr << "Wrong gravity name" << endl;
    exit(1);
}

void test(const char* gravity)
{
    XSetWindowAttributes attrs;
    XSizeHints hints;
    hints.flags = USPosition | PWinGravity;
    hints.win_gravity = get_gravity(gravity);
    Window w = XCreateWindow(dpy, DefaultRootWindow(dpy), 100, 100, 200, 100, 0, CopyFromParent, CopyFromParent,
                             CopyFromParent, 0, &attrs);
    XSetWMNormalHints(dpy, w, &hints);
    XSelectInput(dpy, w, StructureNotifyMask | ButtonPressMask);
    XMapWindow(dpy, w);
    for (;;) {
        XEvent ev;
        XNextEvent(dpy, &ev);
        if (ev.type == ConfigureNotify) {
            cout << "CONFIGURENOTIFY:" << ev.xany.send_event << ":" << ev.xconfigure.x << ":" << ev.xconfigure.y
                 << ":" << ev.xconfigure.width << ":" << ev.xconfigure.height << endl;
            Window root, child;
            int x, x_local, y, y_local;
            unsigned int width, height, border, depth;
            XGetGeometry(dpy, w, &root, &x_local, &y_local, &width, &height, &border, &depth);
            XTranslateCoordinates(dpy, w, root, 0, 0, &x, &y, &child);
            cout << "GEOMETRY:" << x << ":" << y << ":" << width << ":" << height << ":(" << x_local << ":" << y_local << ")" << endl;
        } else if (ev.type == ButtonPress) {
            if (ev.xbutton.button == Button1) { // move
                cout << "MOVE" << endl;
                XMoveWindow(dpy, w, 100, 100);
            } else if (ev.xbutton.button == Button2) { // resize
                cout << "RESIZE" << endl;
                XResizeWindow(dpy, w, 200, 100);
            } else if (ev.xbutton.button == Button3) { // move and resize
                cout << "MOVERESIZE" << endl;
                XMoveResizeWindow(dpy, w, 100, 100, 200, 100);
            }
        }
    }
}

int main(int argc, char* argv[])
{
    dpy = XOpenDisplay(NULL);
    if (argc != 2) {
        cerr << "specify gravity" << endl;
        exit(1);
    }
    test(argv[ 1 ]);
    XCloseDisplay(dpy);
}
