1

I'm using Ubuntu 12.04 in a VM.

Upper left is never correct. Width and height are correct about 90% of the time.

XMoveWindow and friends have no effect on the rendered position of the window.

Source:

#include <stdio.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/X.h>

int main(int argc, char **argv)
{
    Display *disp = XOpenDisplay(0);

    GLint attr[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GX_DOUBLEBUFFER, None};
    XVisualInfo *vinfo = glXChooseVisual(disp,0,attr);

    Window rootWnd = DefaultRootWindow(disp);

    XSetWindowAttributes setWndAttr = {0};
    setWndAttr.colormap = XCreateColormap(disp,rootWnd,vinfo->visual,AllocNone);
    setWndAttr.event_mask =
        ExposureMask|
        StructureNotifyMask;

    Window wnd = XCreateWindow(
        disp,rootWnd,
        64,64,  // can be ignored (asinine)
        512,512,
        0,vinfo->depth,
        InputOutput,
        vinfo->visual,
        CWColormap|CWEventMask,
        &setWndAttr
        );

    XStoreName(disp,wnd,"What is this crap?");
    XMapWindow(disp,wnd);

    // WMs allowed to completely ignore these, too?
    //XMoveWindow(disp,wnd,128,128);
    //XMoveResizeWindow(disp,wnd,128,128,256,256);

    Atom closeWndAtom = XInternAtom(disp,"WM_DELETE_WINDOW",0);
    XSetWMProtocols(disp,wnd,&closeWndAtom,1);

    GLXContext ctx = glCreateContext(disp,vinfo,0,GL_TRUE);
    glXMakeCurrent(disp,wnd,ctx);

    bool run = true;
    XEvent evt;
    while(run){
        XNextEvent(disp,&evt);
        switch(evt.type){
        case Expose:
            {
                XWindowAttributes wndAttr;
                XGetWindowAttributes(disp,wnd,&wndAttr);

                // these are NEVER correct (0,0 most of the time)
                printf("%i, %i\n",wndAttr.x,wndAttr.y);

                // these are correct, most of the time
                //
                // occasionally, either width or height will be 0
                glViewport(0,0,wndAttr.width,wndAttr.height);

                glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
                glBegin(GL_TRIANGLES);
                glColor3f(1,0,0);
                glVertex2f(0,0);
                glColor3f(0,1,0);
                glVertex2f(1,0);
                glColor3f(0,0,1);
                glVertex2f(0,1);
                glEnd();

                glXSwapBuffers(disp,wnd);
            }break;
        case ClientMessage:
            {
                run = false;
            }break;
        }
    }

    glXDestroyContext(disp,ctx);
    XDestroyWindow(disp,wnd);
    XCloseDisplay(disp);
    return 0;
}

Note: There might be a spelling error to two, as pasting from within the VM wouldn't format correctly. As a result, I had to re-type it.

EDIT:

Because clarity is needed here: I don't care what the window manager does with the position I give it, I am interested in retrieving this information from the window manager reliably. The position I am given does not correspond to the rendered position of the window on the screen. For example: The window appears at the lower right of the screen, and the coordinates returned to me are (0,0). Moving the window around using the mouse doesn't change what XGetWindowAttributes returns.

defube
  • 2,395
  • 1
  • 22
  • 34
  • My advice is to never use xlib directly, but use one of the frameworks that exists. Both [SDL](http://www.libsdl.org/) and [SFML](http://www.sfml-dev.org/) (and others of course) are small let you create an OpenGL-aware window in just a line or two. – Some programmer dude Jan 17 '13 at 08:30
  • 4
    1: SDL, Qt, and others are dependencies I cannot allow. 2: It should be possible to write a standalone UI library based on existing documentation. 3: Xlib is not (must not) be exclusively accessible only to those who wish to "market" cross-platform UI toolkits. 4: I despise OO-based UI toolkits. – defube Jan 17 '13 at 08:36
  • how do you compile? what is your question? – BЈовић Jan 17 '13 at 08:36
  • The question is: Why is `XGetWindowAttributes` producing incorrect values? Is it the cause of the window manager? Is it something I did? I don't know, which is why I'm asking here. – defube Jan 17 '13 at 08:37
  • Then I suggest you also add a case for [resize request events](http://tronche.com/gui/x/xlib/events/structure-control/resize.html). – Some programmer dude Jan 17 '13 at 08:43
  • ok, how do you compile? I see some problems in your code – BЈовић Jan 17 '13 at 08:43
  • possible duplicate of [Xlib: window is created in wrong position](http://stackoverflow.com/questions/12820233/xlib-window-is-created-in-wrong-position) – BЈовић Jan 17 '13 at 08:50
  • @BЈовић: icpc main.cpp -LX11 -LGL, I think. I'm building using eclipse. – defube Jan 17 '13 at 09:22
  • Window managers can reparent. The coordinates are relative to the parent. Use `XTranslateCoordinates`. – n. m. could be an AI Jan 18 '13 at 06:58
  • @n.m: I discovered this earlier today. Make that an answer and I'll accept it (this comment list is getting obnoxiously long). – defube Jan 18 '13 at 07:25
  • Found this question as I was searching for why the window isn't getting created at the specified x,y .... Its indeed asinine – Karan Joisher Oct 01 '18 at 17:08

3 Answers3

3

It seems you are polling window information from Expose event, which may not have newest information about window at the time. Use ConfigureNotify event and it's properties to get updated position and size:

// you need to have this in your event mask(you've already got that):
EVENT_MASK |= StructureNotifyMask;

// in your event loop
// ...
case ConfigureNotify: // resize or move event
    printf("x: %d, y:%d, width: %d, height: %d\n", 
           event.xconfigure.x,
           event.xconfigure.y,
           event.xconfigure.width,
           event.xconfigure.height);
    break;
vlsh
  • 175
  • 8
2

I think, one of the option is to use XTranslateCoordinates:

XTranslateCoordinates(dpy,
                      wnd,         // get position for this window
                      root_window, // something like macro: DefaultRootWindow(dpy)
                      0, 0,        // local left top coordinates of the wnd
                      &dest_x,     // these is position of wnd in root_window
                      &dest_y,     // ...
                      &unused);

You also can use XGetGeometry instead of XGetWindowAttributes to get left, top, width and height of a drawable. As far as I know XGetWindowAttributes calls XGetGeometry to retrieve some of the attributes.

0

I know, I'm necroposter, but I was also looking for the answer and found out that the incorrect coordinates are related to Window Manager.

    {
    case ConfigureNotify :
        printf("%d, %d : %u, %u\n",
                event.xconfigure.x, event.xconfigure.y,
                event.xconfigure.width, event.xconfigure.height);
        break;
    }

# Moving window
353, 100 : 791, 600
363, 113 : 791, 600
# Changing window size
1, 24 : 791, 600 << Pay attention to this
363, 113 : 791, 600
363, 113 : 791, 600

For the additional info you need to read ICCCM (4.1.5. Configuring the Window, 4.2.3. Window Move, 4.2.4. Window Resize) https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.5

Alex Tiger
  • 377
  • 3
  • 22