tglas
tglas

Reputation: 1010

How to resize a window programmatically with X11lib?

I am creating an X11 window, which is then resized programmatically with XWindowResize:

#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <cassert>
#include <cstdio>

int main()
{
    Display* display = XOpenDisplay(nullptr);
    assert(display);

    Window root = DefaultRootWindow(display);
    assert(root);

    GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
    XVisualInfo* vi = glXChooseVisual(display, 0, att);
    assert(vi);

    XSetWindowAttributes swa;
    swa.colormap = XCreateColormap(display, root, vi->visual, AllocNone);
    swa.event_mask = ExposureMask | KeyPressMask;

    // create window with initial size 800 x 600
    Window window = XCreateWindow(display, root, 0, 0, 800, 600, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
    XSelectInput(display, window, StructureNotifyMask | ResizeRedirectMask);
    XMapWindow(display, window);
    XFlush(display);

    // resize window to new size 400 x 300
    int result = XResizeWindow(display, window, 400, 300);
    printf("XResizeWindow  return value: %d\n", result);
    if (result == BadValue) printf("   bad value!!!\n");
    if (result == BadWindow) printf("   bad window!!!\n");

    XEvent event;
    XAnyEvent& ev = (XAnyEvent&)event;
    while (true)
    {
        XNextEvent(display, &event);

        if (ev.type == ResizeRequest)
        {
            XResizeRequestEvent& ev = (XResizeRequestEvent&)event;
            printf("request to resize to %d x %d\n", ev.width, ev.height);
        }

        XWindowAttributes xwa;
        XGetWindowAttributes(display, window, &xwa);
        printf("position: %d, %d     size: %d x %d\n", xwa.x, xwa.y, xwa.width, xwa.height);
    }
}

This is not working as expected. The window decoration drawn by the window manager indicates that it is indeed resized to 400x300 pixels, however, XGetWindowAttributes reports the contrary (output below). Changing position and size manually with the mouse has the same effect: the resize request reports the correct size, but it is not reflected in the output of XGetWindowAttributes. The problem is that this affects the area in which mouse events are detected as well as OpenGL drawing (removed in order to have a minimal example).

XResizeWindow  return value: 1
position: 1, 30     size: 800 x 600
position: 1, 30     size: 800 x 600
request to resize to 400 x 300
position: 1, 30     size: 800 x 600
position: 1, 30     size: 800 x 600
position: 1, 30     size: 800 x 600

Apparently I am doing it wrong. I'd appreciate any help on how to make this work. Do I have to do anything in order to honor the resize request? I have searched the web and stackoverflow for hours now without luck.

EDIT: It would already be helpful if someone could tell me whether the XResizeWindow return value of 1 indicates an error or not. I am unable to find documentation on the return value in case there is no error. Also, links to documentation containing this information are more than welcome!

Upvotes: 4

Views: 4522

Answers (1)

n. m. could be an AI
n. m. could be an AI

Reputation: 119857

Don't request ResizeRedirectMask. It is supposed to be requested by one client at a time, which is normally your window manager. Except WMs usually request SubstructureNotifyMaks on the root, which takes precedence over ResizeRedirectMask on the children, so that the latter is quite useless. I couldn't find one single example of a program, WM or otherwise, that uses ResizeRedirectMask.

If you do request ResizeRedirectMask, your window attributes may be stuck with a wrong size.

If you need to catch actual size changes, request StructureNotifyMask and process ConfigureNotify events.

Upvotes: 4

Related Questions