]> git.sur5r.net Git - i3/i3/commitdiff
Handle the _NET_REQUEST_FRAME_EXTENTS ClientMessage (java compat)
authorMichael Stapelberg <michael@stapelberg.de>
Sat, 27 Jul 2013 13:06:08 +0000 (15:06 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sat, 27 Jul 2013 13:06:08 +0000 (15:06 +0200)
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

include/atoms.xmacro
src/handlers.c

index ac32d8daeee1073408b2653f4668ced04b280224..41889eb1a0c3f242ff50a40611c32cb1683c2701 100644 (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)
index 6be2a5b1f81ae0bfbbaab867c1a708956bc82e13..133d85d04818fad12445ce4fa2e0ffe7d7d432a1 100644 (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, 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;