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;