Home > database >  Cannot Reparent even after Unmapping in X11
Cannot Reparent even after Unmapping in X11

Time:03-07

I am working with X11 and want to perform a re-parent. I got an example hello world application from enter image description here

But when I remove the lines labeled map the smaller window and unmap the smaller window to reparent it, I get the correct result:

image

Shouldn't both yield the same correct result. All I am doing in the original is mapping, then immediately unmapping.

CodePudding user response:

I just reproduced that behavior on my Linux machine.

The problem seems to be a timing problem between your program and the "Window manager".

The "Window manager" is the program which is responsible for drawing the title bar and maybe borders at the windows. The "Window manager" works like this:

Whenever a window is mapped on the root window, the "Window manager" is notified by X11. The "Window manager" creates an "outer window" that contains the title bar and the border. Then it reparents the window so the window becomes a child window of the "outer window".

Example:

enter image description here

If the "Window manager" handles some window after being mapped, it becomes a child window of the "outer window"; for this reason, any window that is not a child window of an "outer window" is obviously not handled by the "Window manager" if it is mapped.

... at least in the "normal case".

For this reason, the "Window manager" does not care about windows that are un-mapped on the root window (but only about windows that are un-mapped from an "outer window").

Normally, the "Window manager" behaves like this:

Your program                      Window manager
------------                      --------------
XMapWindow(d, w2);
XFlush(d);                        
                                  
                                  wm_w2 = XCreateWindow(...);
                                  XUnmapWindow(..., w2);
                                  XReparentWindow(..., w2, wm_w2, ...);
                                  XMapWindow(..., w2);

XUnmapWindow(d, w2);
XFlush(d);

                                  XReparentWindow(..., w2, root, ...);
                                  XDestroyWindow(... wm_w2);

XReparentWindow(d, w2, w, 500, 500);
XMapWindow(d, w2);

   ...                                  ...

However, your program performs XMapWindow() and XUnmapWindow() without enough time for the "Window manager" to react.

For this reason, it is possible (and probable) that the two programs work in the following order:

Your program                      Window manager
------------                      --------------
XMapWindow(d, w2);
XFlush(d);                        // Here the window manager
                                  // is notified about window w2

XUnmapWindow(d, w2);
XFlush(d);                        // The window manager will ignore
                                  // w2 being un-mapped because
                                  // it is not the child of an
                                  // "outer window", yet!

XReparentWindow(d, w2, w, 500, 500);
XMapWindow(d, w2);

   ...                                  ...

                                  // The window manager received the
                                  // notification using XNextEvent()
                                  wm_w2 = XCreateWindow(...);
                                  XUnmapWindow(..., w2);
                                  XReparentWindow(..., w2, wm_w2, ...);
                                  XMapWindow(..., w2);

You have to wait some time between the XMapWindow() and XUnmapWindow() to allow the "Window manager" to re-parent the window in the way it is done by "Window managers".

Otherwise, the "Window manager" will do the re-parenting after you did that!

By the way: On my computer, the problem can be reproduced in a much simpler way:

Create one window, map it and un-map it immediately after this...

The window will be shown although the last function called was XUnmapWindow().

  • Related