ConfigureNotify - Are x,y parent-relative or root-relative?

Jeremy Huddleston jeremyhu at
Wed Nov 12 23:24:54 PST 2008

On Nov 12, 2008, at 15:51, George Staplin wrote:

> In the tarball I've attached there is a withdraw_remap.tcl that I  
> run with wish8.5 for X11 from macports.
> If you have it initially mapped, and drag it to another position  
> before it becomes unmapped (by pressing Begin), and then it's mapped  
> again, it always seems to map in the +0+0 corner.  I think it should  
> probably keep the previous x,y position.  There don't seem to be any  
> hints set that request +0+0.

Hmm... interesting.  Do you know if this worked with the "old" quartz- 
wm?  If so, then it's probably somehow related to the gravity  
changes... but xwininfo -all doesn't show the gravity bit set, so it  
should be acting the same as before... interesting...

This may have something to do with my not 100% understanding what x  
and y are supposed to be in the ConfigureNotify and ConfigureRequest  
events.  (can someone please chime in and fix my brain, thanks)

The documentation says that they are supposed to be the x and y  
relative to the parent window (ie the upper left of the frame):

The x and y members are used to set the window's x and y coordinates,  
which are relative to the parent's origin and indicate the position of  
the upper-left outer corner of the window. The width and height  
members are used to set the inside size of the window, not including  
the border, and must be nonzero.

but that dosen't seem to be the case.  The following is from  
metacity's test-gravity.c:

              if(!ev.xconfigure.send_event) {
                  XTranslateCoordinates(d, windows[i],  
DefaultRootWindow (d),
                                        0, 0,
              } else {
                  window_rects[i].x = ev.xconfigure.x;
                  window_rects[i].y = ev.xconfigure.y;

which makes it seem that the x and y are "global" when from an  
XSendEvent() but parent-relative when from an  
XConfigureNotify()..?!?.. (/slap whoever convoluted this beyond  

When we send the ConfigureNotify event in quartz-wm, we actually need  
to send the x,y relative to the root window or we get the wrong  
positions in that above test app (and also wine has some issues that  
you can see clicking on the smiley in winemine):

- (void) send_configure {
    XEvent e;

    e.type = ConfigureNotify;
    e.xconfigure.display = x_dpy;
    e.xconfigure.event = _id;
    e.xconfigure.window = _id;
    e.xconfigure.x = _xattr.x;
    e.xconfigure.y = _xattr.y;
    if(_reparented) {
        e.xconfigure.x += _current_frame.origin.x;
        e.xconfigure.y += _current_frame.origin.y;
    e.xconfigure.width = _xattr.width;
    e.xconfigure.height = _xattr.height;
    e.xconfigure.border_width = _xattr.border_width;
    e.xconfigure.above = _reparented ? _frame_id : _screen->_root;
    e.xconfigure.override_redirect = False;

    XSendEvent(x_dpy, _id, False, StructureNotifyMask, &e);


When we process the ConfigureRequestEvent we send a ConfigureNotify to  
the decoration/frame window using XConfigureWindow:

static void
x_event_configure_request (XConfigureRequestEvent *e)
    x_window *w = x_get_window (e->window);

    XWindowChanges client_changes, real_frame_changes, *frame_changes;
    unsigned long client_mask, real_frame_mask, *frame_mask;
    CGRect client_rect;

    if (w != nil && e->window != w->_id)
        w = nil;

    if (w == nil)
        /* whatever.. */

        client_changes.stack_mode = e->detail;
        client_changes.sibling = e->above;
        client_changes.x = e->x;
        client_changes.y = e->y;
        client_changes.width = e->width;
        client_changes.height = e->height;

        XConfigureWindow (x_dpy, e->window, e->value_mask,  


    if (e->value_mask & CWBorderWidth)
        w->_xattr.border_width = e->border_width;

    //[w update_shaped];

    client_mask = real_frame_mask = 0;

    frame_changes = w->_reparented ? &real_frame_changes :  
    frame_mask = w->_reparented ? &real_frame_mask : &client_mask;

    if (e->value_mask & CWStackMode)
        frame_changes->stack_mode = e->detail;
        *frame_mask |= CWStackMode;

        if (e->value_mask & CWSibling)
            frame_changes->sibling = e->above;
            *frame_mask |= CWSibling;

    client_rect = CGRectMake (w->_xattr.x, w->_xattr.y,
                              w->_xattr.width, w->_xattr.height);
    if (e->value_mask & CWX)
        client_rect.origin.x = e->x;
    if (e->value_mask & CWY)
        client_rect.origin.y = e->y;
    if (e->value_mask & CWWidth)
        client_rect.size.width = e->width;
    if (e->value_mask & CWHeight)
        client_rect.size.height = e->height;

    [w resize_client:client_rect];

    if (real_frame_mask != 0)
        XConfigureWindow (x_dpy, w->_frame_id,
                          real_frame_mask, &real_frame_changes);

    if (client_mask != 0)
        XConfigureWindow (x_dpy, w->_id, client_mask, &client_changes);

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3040 bytes
Desc: not available
URL: <>

More information about the xorg mailing list