Search code examples
c++x11

After XResizeWindow, X11 is not updating the WindowAttributes


I am trying to resize a window and get an image using X11 in my cpp program. Though, I can't seem to figure out how to update the window attributes with the new width and height.

When calling XResize, my window does resize on my system, but when calling XGetWindowAttributes, the width & height variables are still the original values.

I have tried remapping my window, searching for my window again after resizing, keeping the updated width and height attributes in variables instead of getting window attributes (this crashes the application when trying to call for a SubImage). Currently, if I keep the window with the original values, when the resized window is larger than the original, the overflow of my image is cut off.

Here is the snippet I am testing with, I am using an instance of alacritty as my test window:

void SomeFunction(int w, int h){
  std::cout << "Expected: " << w << " : " << h << std::endl;
  XResizeWindow(m_display, *m_window, w, h);

  XWindowAttributes attributes;
  XGetWindowAttributes(m_display, *m_window, &attributes);
  std::cout << "Actual: " << attributes.width << " : " << attributes.height << std::endl;
}

Output:

Expected 853 : 480
Actual: 800 : 600

Solution

  • Here is my current working solution to this issue.

    (NOTE: The linked repository is under the AGPL License)

    The solution I came to still involves finding the window again, similar to below. Though, it is important to use ConfigureNotify, as mentioned by @SamVarshavchick. You MUST wait for your resize event to be recieved. Else, when searching for the window, the result may be the original as the window resize is still being processed.

    Deprecated Answer:

    I have fixed the issue.. the windows width and height attributes do not update automatically. An explanation on why this is I cannot provide, but finding the window again does update the attributes.

    Fix:

    void SomeFunction(int w, int h){
        std::cout << "Expected: " << w << " : " << h << std::endl;
        XResizeWindow(m_display, *m_window, w, h);
        m_window = this->findWindowByName(m_rootWindow); // Find the window again
        XWindowAttributes attributes;
        XGetWindowAttributes(m_display, *m_window, &attributes);
        m_xImage = XGetImage(m_display, // Update the image we are working with
                *m_window,
                0,
                0,
                attributes.width,
                attributes.height,
                AllPlanes,
                ZPixmap);
        std::cout << "Actual: " << attributes.width << " : " << attributes.height << std::endl;
    }
    

    I don't like this solution for two reasons.

    • Spending resources on finding the window again.
    • Calling XGetImage is high cost, it saves a copy of the image in the library which does not free until the program ends. My program primarily uses XGetSubImage to get around this.