Search code examples
c++windowx11xlib

Segmentation fault on XQueryTree


I'm trying to close the last used window (the one right under the current window in the stacking order). Unfortunately XQueryTree segfaults for some reason.

#pragma once

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

namespace WindowingOperations {

    inline void closeLastWindow() {
        Display* dpy = XOpenDisplay(0);
        Window root = DefaultRootWindow(dpy);

        Window* root_return;
        Window* parent_return;
        Window** children_return;
        unsigned int* nchildren_return;

        XQueryTree(dpy,
                   root,
                   root_return,
                   parent_return,
                   children_return,
                   nchildren_return);

        // Kill the window right after this one
        if (*nchildren_return > 1)
            XDestroyWindow(dpy, *children_return[*nchildren_return - 2]);
    }
}

EDIT:

If you need a test case:

#include "window_operations.h"
int main() {
    WindowingOperations::closeLastWindow();
    return 0;
}

Solution

  • The _return parameters need somewhere to go. You can't just pass in uninitialized pointers, storage needs to be allocated for XQueryTree to write the results in.

    So...

    namespace WindowingOperations {
    
        inline void closeLastWindow() {
            Display* dpy = XOpenDisplay(0);
            Window root = DefaultRootWindow(dpy);
    
        // Allocate storage for the results of XQueryTree. 
            Window root_return;
            Window parent_return;
            Window* children_return;
            unsigned int nchildren_return;
    
        // then make the call providing the addresses of the out parameters
            if (XQueryTree(dpy,
                           root,
                           &root_return,
                           &parent_return,
                           &children_return,
                           &nchildren_return) != 0)
            { // added if to test for a failed call. results are unchanged if call failed, 
              // so don't use them
    
                // Kill the window right after this one
                if (*nchildren_return > 1)
                    XDestroyWindow(dpy, *children_return[*nchildren_return - 2]);
            }
            else
            {
                // handle error
            }
        }
    }