Handle the _NET_REQUEST_FRAME_EXTENTS ClientMessage (java compat)

This ClientMessage can be used to estimate how big the window will be
before opening it. Java always sends the ClientMessage and checks the
atom that should be set by the window manager, but it seems that the
fallback code path has a race condition.

Let’s see if the situation gets better with this change. I have been
running this patch for about two weeks and have not seen any issues with
it.

fixes #934
fixes #709
This commit is contained in:
Michael Stapelberg 2013-07-27 15:06:08 +02:00
parent 88671986f4
commit 0c7a76c2f1
2 changed files with 41 additions and 0 deletions

View File

@ -29,3 +29,5 @@ xmacro(I3_CONFIG_PATH)
xmacro(I3_SYNC)
xmacro(I3_SHMLOG_PATH)
xmacro(I3_PID)
xmacro(_NET_REQUEST_FRAME_EXTENTS)
xmacro(_NET_FRAME_EXTENTS)

View File

@ -691,6 +691,45 @@ static void handle_client_message(xcb_client_message_event_t *event) {
xcb_send_event(conn, false, window, XCB_EVENT_MASK_NO_EVENT, (char*)ev);
xcb_flush(conn);
free(reply);
} else if (event->type == A__NET_REQUEST_FRAME_EXTENTS) {
// A client can request an estimate for the frame size which the window
// manager will put around it before actually mapping its window. Java
// does this (as of openjdk-7).
//
// Note that the calculation below is not entirely accurate — once you
// set a different border type, its off. We _could_ request all the
// window properties (which have to be set up at this point according
// to EWMH), but that seems rather elaborate. The standard explicitly
// says the application must cope with an estimate that is not entirely
// accurate.
DLOG("_NET_REQUEST_FRAME_EXTENTS for window 0x%08x\n", event->window);
xcb_get_geometry_reply_t *geometry;
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(conn, event->window);
if (!(geometry = xcb_get_geometry_reply(conn, cookie, NULL))) {
ELOG("Could not get geometry of X11 window 0x%08x while handling "
"the _NET_REQUEST_FRAME_EXTENTS ClientMessage\n",
event->window);
return;
}
DLOG("Current geometry = x=%d, y=%d, width=%d, height=%d\n",
geometry->x, geometry->y, geometry->width, geometry->height);
Rect r = {
0, // left
geometry->width + 4, // right
0, // top
geometry->height + config.font.height + 5, // bottom
};
xcb_change_property(
conn,
XCB_PROP_MODE_REPLACE,
event->window,
A__NET_FRAME_EXTENTS,
XCB_ATOM_CARDINAL, 32, 4,
&r);
xcb_flush(conn);
} else {
DLOG("unhandled clientmessage\n");
return;