From: Michael Stapelberg Date: Sat, 27 Jul 2013 13:06:08 +0000 (+0200) Subject: Handle the _NET_REQUEST_FRAME_EXTENTS ClientMessage (java compat) X-Git-Tag: 4.6~3 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=0c7a76c2f158597905fb9a27d979310f57b4141f;p=i3%2Fi3 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 --- diff --git a/include/atoms.xmacro b/include/atoms.xmacro index ac32d8da..41889eb1 100644 --- a/include/atoms.xmacro +++ b/include/atoms.xmacro @@ -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) diff --git a/src/handlers.c b/src/handlers.c index 6be2a5b1..133d85d0 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -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, it’s 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;