]> git.sur5r.net Git - i3/i3/blobdiff - i3bar/src/xcb.c
Ensure all *.[ch] files include config.h
[i3/i3] / i3bar / src / xcb.c
index 0b9f094bdbe2859026e65271741540abe80d37eb..2715e44711cb327be871f07ec4653070a351b917 100644 (file)
@@ -7,16 +7,14 @@
  * xcb.c: Communicating with X
  *
  */
+#include "common.h"
+
 #include <xcb/xcb.h>
 #include <xcb/xkb.h>
 #include <xcb/xproto.h>
 #include <xcb/xcb_aux.h>
 #include <xcb/xcb_cursor.h>
 
-#ifdef XCB_COMPAT
-#include "xcb_compat.h"
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -36,7 +34,6 @@
 #include <sanitizer/lsan_interface.h>
 #endif
 
-#include "common.h"
 #include "libi3.h"
 
 /** This is the equivalent of XC_left_ptr. I’m not sure why xcb doesn’t have a
@@ -445,7 +442,7 @@ void init_colors(const struct xcb_color_strings_t *new_colors) {
 
 /*
  * Handle a button press event (i.e. a mouse click on one of our bars).
- * We determine, whether the click occured on a workspace button or if the scroll-
+ * We determine, whether the click occurred on a workspace button or if the scroll-
  * wheel was used and change the workspace appropriately
  *
  */
@@ -689,15 +686,17 @@ static void handle_client_message(xcb_client_message_event_t *event) {
         if (op == SYSTEM_TRAY_REQUEST_DOCK) {
             xcb_window_t client = event->data.data32[2];
 
-            /* Listen for PropertyNotify events to get the most recent value of
-             * the XEMBED_MAPPED atom, also listen for UnmapNotify events */
             mask = XCB_CW_EVENT_MASK;
-            values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE |
-                        XCB_EVENT_MASK_STRUCTURE_NOTIFY;
-            xcb_change_window_attributes(xcb_connection,
-                                         client,
-                                         mask,
-                                         values);
+
+            /* Needed to get the most recent value of XEMBED_MAPPED. */
+            values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE;
+            /* Needed for UnmapNotify events. */
+            values[0] |= XCB_EVENT_MASK_STRUCTURE_NOTIFY;
+            /* Needed because some tray applications (e.g., VLC) use
+             * override_redirect which causes no ConfigureRequest to be sent. */
+            values[0] |= XCB_EVENT_MASK_RESIZE_REDIRECT;
+
+            xcb_change_window_attributes(xcb_connection, client, mask, values);
 
             /* Request the _XEMBED_INFO property. The XEMBED specification
              * (which is referred by the tray specification) says this *has* to
@@ -769,19 +768,9 @@ static void handle_client_message(xcb_client_message_event_t *event) {
                     break;
             }
 
-            /* Check whether any "tray_output primary" was defined for this bar. */
-            bool contains_primary = false;
-            TAILQ_FOREACH(tray_output, &(config.tray_outputs), tray_outputs) {
-                if (strcasecmp("primary", tray_output->output) == 0) {
-                    contains_primary = true;
-                    break;
-                }
-            }
-
-            /* In case of tray_output == primary and there is no primary output
-             * configured, we fall back to the first available output. We do the
-             * same if no tray_output was specified. */
-            if (output == NULL && (contains_primary || TAILQ_EMPTY(&(config.tray_outputs)))) {
+            /* If no tray_output has been specified, we fall back to the first
+             * available output. */
+            if (output == NULL && TAILQ_EMPTY(&(config.tray_outputs))) {
                 SLIST_FOREACH(walk, outputs, slist) {
                     if (!walk->active)
                         continue;
@@ -790,6 +779,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
                     break;
                 }
             }
+
             if (output == NULL) {
                 ELOG("No output found\n");
                 return;
@@ -824,7 +814,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
             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[1] = XEMBED_EMBEDDED_NOTIFY;
             ev->data.data32[2] = output->bar.id;
             ev->data.data32[3] = xe_version;
             xcb_send_event(xcb_connection,
@@ -1017,13 +1007,11 @@ static void handle_property_notify(xcb_property_notify_event_t *event) {
 }
 
 /*
- * Handle ConfigureRequests by denying them and sending the client a
- * ConfigureNotify with its actual size.
+ * If a tray client attempts to change its size we deny the request and respond
+ * by telling it its actual size.
  *
  */
-static void handle_configure_request(xcb_configure_request_event_t *event) {
-    DLOG("ConfigureRequest for window = %08x\n", event->window);
-
+static void handle_configuration_change(xcb_window_t window) {
     trayclient *trayclient;
     i3_output *output;
     SLIST_FOREACH(output, outputs, slist) {
@@ -1036,7 +1024,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
                 continue;
             clients++;
 
-            if (trayclient->win != event->window)
+            if (trayclient->win != window)
                 continue;
 
             xcb_rectangle_t rect;
@@ -1046,7 +1034,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
             rect.height = icon_size;
 
             DLOG("This is a tray window. x = %d\n", rect.x);
-            fake_configure_notify(xcb_connection, rect, event->window, 0);
+            fake_configure_notify(xcb_connection, rect, window, 0);
             return;
         }
     }
@@ -1054,6 +1042,16 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
     DLOG("WARNING: Could not find corresponding tray window.\n");
 }
 
+static void handle_configure_request(xcb_configure_request_event_t *event) {
+    DLOG("ConfigureRequest for window = %08x\n", event->window);
+    handle_configuration_change(event->window);
+}
+
+static void handle_resize_request(xcb_resize_request_event_t *event) {
+    DLOG("ResizeRequest for window = %08x\n", event->window);
+    handle_configuration_change(event->window);
+}
+
 /*
  * This function is called immediately before the main loop locks. We flush xcb
  * then (and only then)
@@ -1094,7 +1092,7 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
             DLOG("received an xkb event\n");
 
             xcb_xkb_state_notify_event_t *state = (xcb_xkb_state_notify_event_t *)event;
-            if (state->xkbType == XCB_XKB_STATE_NOTIFY) {
+            if (state->xkbType == XCB_XKB_STATE_NOTIFY && config.modifier != XCB_NONE) {
                 int modstate = state->mods & config.modifier;
 
 #define DLOGMOD(modmask, status)                        \
@@ -1179,6 +1177,9 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
             case XCB_CONFIGURE_REQUEST:
                 /* ConfigureRequest, sent by a tray child */
                 handle_configure_request((xcb_configure_request_event_t *)event);
+            case XCB_RESIZE_REQUEST:
+                /* ResizeRequest sent by a tray child using override_redirect. */
+                handle_resize_request((xcb_resize_request_event_t *)event);
                 break;
         }
         free(event);
@@ -1770,16 +1771,35 @@ void reconfig_windows(bool redraw_bars) {
             }
 
             /* Unless "tray_output none" was specified, we need to initialize the tray. */
-            const char *first = (TAILQ_EMPTY(&(config.tray_outputs))) ? SLIST_FIRST(outputs)->name : TAILQ_FIRST(&(config.tray_outputs))->output;
-            if (!tray_configured && strcasecmp(first, "none") != 0) {
-                /* We do a sanity check here to ensure that this i3bar instance actually handles
-                 * the output on which the tray should appear. For example,
-                 * consider tray_output == [VGA-1], but output == [HDMI-1]. */
+            bool no_tray = false;
+            if (!(TAILQ_EMPTY(&(config.tray_outputs)))) {
+                no_tray = strcasecmp(TAILQ_FIRST(&(config.tray_outputs))->output, "none") == 0;
+            }
 
+            /*
+             * There are three scenarios in which we need to initialize the tray:
+             *   1. A specific output was listed in tray_outputs which is also
+             *      in the list of outputs managed by this bar.
+             *   2. No tray_output directive was specified. In this case, we
+             *      use the first available output.
+             *   3. 'tray_output primary' was specified. In this case we use the
+             *      primary output.
+             *
+             * Three scenarios in which we specifically don't want to
+             * initialize the tray are:
+             *   1. 'tray_output none' was specified.
+             *   2. A specific output was listed as a tray_output, but is not
+             *      one of the outputs managed by this bar. For example, consider
+             *      tray_outputs == [VGA-1], but outputs == [HDMI-1].
+             *   3. 'tray_output primary' was specified and no output in the list
+             *      is primary.
+             */
+            if (!tray_configured && !no_tray) {
                 /* If no tray_output was specified, we go ahead and initialize the tray as
                  * we will be using the first available output. */
-                if (TAILQ_EMPTY(&(config.tray_outputs)))
+                if (TAILQ_EMPTY(&(config.tray_outputs))) {
                     init_tray();
+                }
 
                 /* If one or more tray_output assignments were specified, we ensure that at least one of
                  * them is actually an output managed by this instance. */