From 893878cbcc7306a6553cda51b3423c73c25e9e99 Mon Sep 17 00:00:00 2001
From: Michael Stapelberg <michael@stapelberg.de>
Date: Wed, 17 Aug 2011 00:44:03 +0200
Subject: [PATCH] i3bar: send XEMBED_EMBEDDED_NOTIFY after reparenting/mapping
 tray clients

---
 i3bar/include/trayclients.h |  1 +
 i3bar/include/xcb.h         |  1 +
 i3bar/include/xcb_atoms.def |  1 +
 i3bar/src/xcb.c             | 32 ++++++++++++++++++++++++++++----
 4 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/i3bar/include/trayclients.h b/i3bar/include/trayclients.h
index 277cd1cb..1113daeb 100644
--- a/i3bar/include/trayclients.h
+++ b/i3bar/include/trayclients.h
@@ -18,6 +18,7 @@ TAILQ_HEAD(tc_head, trayclient);
 struct trayclient {
     xcb_window_t       win;         /* The window ID of the tray client */
     bool               mapped;      /* Whether this window is mapped */
+    int                xe_version;  /* The XEMBED version supported by the client */
 
     TAILQ_ENTRY(trayclient) tailq;  /* Pointer for the TAILQ-Macro */
 };
diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h
index 3fadc4c5..b70d29ef 100644
--- a/i3bar/include/xcb.h
+++ b/i3bar/include/xcb.h
@@ -16,6 +16,7 @@
 #define SYSTEM_TRAY_BEGIN_MESSAGE   1
 #define SYSTEM_TRAY_CANCEL_MESSAGE  2
 #define XEMBED_MAPPED                   (1 << 0)
+#define XEMBED_EMBEDDED_NOTIFY		0
 
 struct xcb_color_strings_t {
     char *bar_fg;
diff --git a/i3bar/include/xcb_atoms.def b/i3bar/include/xcb_atoms.def
index 3f2b9775..625fc8a4 100644
--- a/i3bar/include/xcb_atoms.def
+++ b/i3bar/include/xcb_atoms.def
@@ -9,4 +9,5 @@ ATOM_DO(_NET_SYSTEM_TRAY_VISUAL)
 ATOM_DO(CARDINAL)
 ATOM_DO(_NET_SYSTEM_TRAY_OPCODE)
 ATOM_DO(_XEMBED_INFO)
+ATOM_DO(_XEMBED)
 #undef ATOM_DO
diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c
index c7ddfe88..81c00ac4 100644
--- a/i3bar/src/xcb.c
+++ b/i3bar/src/xcb.c
@@ -435,6 +435,7 @@ void handle_client_message(xcb_client_message_event_t* event) {
              * (which is referred by the tray specification) says this *has* to
              * be set, but VLC does not set it… */
             bool map_it = true;
+            int xe_version = 1;
             xcb_get_property_cookie_t xembedc;
             xembedc = xcb_get_property_unchecked(xcb_connection,
                                                  0,
@@ -453,6 +454,9 @@ void handle_client_message(xcb_client_message_event_t* event) {
                 DLOG("xembed version = %d\n", xembed[0]);
                 DLOG("xembed flags = %d\n", xembed[1]);
                 map_it = ((xembed[1] & XEMBED_MAPPED) == XEMBED_MAPPED);
+                xe_version = xembed[0];
+                if (xe_version > 1)
+                    xe_version = 1;
                 free(xembedr);
             } else {
                 ELOG("Window %08x violates the XEMBED protocol, _XEMBED_INFO not set\n", client);
@@ -484,6 +488,24 @@ void handle_client_message(xcb_client_message_event_t* event) {
                                  mask,
                                  values);
 
+            /* send the XEMBED_EMBEDDED_NOTIFY message */
+            void *event = calloc(32, 1);
+            xcb_client_message_event_t *ev = event;
+            ev->response_type = XCB_CLIENT_MESSAGE;
+            ev->window = client;
+            ev->type = atoms[_XEMBED];
+            ev->format = 32;
+            ev->data.data32[0] = XCB_CURRENT_TIME;
+            ev->data.data32[1] = atoms[XEMBED_EMBEDDED_NOTIFY];
+            ev->data.data32[2] = output->bar;
+            ev->data.data32[3] = xe_version;
+            xcb_send_event(xcb_connection,
+                           0,
+                           client,
+                           XCB_EVENT_MASK_NO_EVENT,
+                           (char*)ev);
+            free(event);
+
             if (map_it) {
                 DLOG("Mapping dock client\n");
                 xcb_map_window(xcb_connection, client);
@@ -493,6 +515,7 @@ void handle_client_message(xcb_client_message_event_t* event) {
             trayclient *tc = malloc(sizeof(trayclient));
             tc->win = client;
             tc->mapped = map_it;
+            tc->xe_version = xe_version;
             TAILQ_INSERT_TAIL(output->trayclients, tc, tailq);
 
             /* Trigger an update to copy the statusline text to the appropriate
@@ -533,12 +556,12 @@ static void handle_property_notify(xcb_property_notify_event_t *event) {
         event->state == XCB_PROPERTY_NEW_VALUE) {
         DLOG("xembed_info updated\n");
         trayclient *trayclient = NULL, *walk;
-        i3_output *output;
-        SLIST_FOREACH(output, outputs, slist) {
-            if (!output->active)
+        i3_output *o_walk;
+        SLIST_FOREACH(o_walk, outputs, slist) {
+            if (!o_walk->active)
                 continue;
 
-            TAILQ_FOREACH(walk, output->trayclients, tailq) {
+            TAILQ_FOREACH(walk, o_walk->trayclients, tailq) {
                 if (walk->win != event->window)
                     continue;
                 trayclient = walk;
@@ -907,6 +930,7 @@ void init_tray() {
                    xcb_root,
                    XCB_EVENT_MASK_STRUCTURE_NOTIFY,
                    (char*)ev);
+    free(event);
 }
 
 /*