]> git.sur5r.net Git - i3/i3/blobdiff - i3bar/src/xcb.c
Fix i3bar when using multiple displays (Thanks brimstone)
[i3/i3] / i3bar / src / xcb.c
index a9ecc004489afe50bec055abd805101b8eae917b..afcfaa397420791d68f21928a3f87646ccd4b0ea 100644 (file)
@@ -2,17 +2,15 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3bar - an xcb-based status- and ws-bar for i3
+ * © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
  *
- * © 2010-2011 Axel Wagner and contributors
- *
- * See file LICNSE for license information
- *
- * src/xcb.c: Communicating with X
+ * xcb.c: Communicating with X
  *
  */
 #include <xcb/xcb.h>
 #include <xcb/xproto.h>
 #include <xcb/xcb_atom.h>
+#include <xcb/xcb_aux.h>
 
 #ifdef XCB_COMPAT
 #include "xcb_compat.h"
 #include "common.h"
 #include "libi3.h"
 
-#if defined(__APPLE__)
-
-/*
- * Taken from FreeBSD
- * Returns a pointer to a new string which is a duplicate of the
- * string, but only copies at most n characters.
- *
- */
-char *strndup(const char *str, size_t n) {
-    size_t len;
-    char *copy;
-
-    for (len = 0; len < n && str[len]; len++)
-        continue;
-
-    copy = smalloc(len + 1);
-    memcpy(copy, str, len);
-    copy[len] = '\0';
-    return (copy);
-}
-
-#endif
-
 /* We save the Atoms in an easy to access array, indexed by an enum */
 enum {
     #define ATOM_DO(name) name,
@@ -194,21 +169,6 @@ void draw_text(xcb_drawable_t drawable, xcb_gcontext_t ctx, int16_t x, int16_t y
     }
 }
 
-/*
- * Converts a colorstring to a colorpixel as expected from xcb_change_gc.
- * s is assumed to be in the format "rrggbb"
- *
- */
-uint32_t get_colorpixel(const char *s) {
-    char strings[3][3] = { { s[0], s[1], '\0'} ,
-                           { s[2], s[3], '\0'} ,
-                           { s[4], s[5], '\0'} };
-    uint8_t r = strtol(strings[0], NULL, 16);
-    uint8_t g = strtol(strings[1], NULL, 16);
-    uint8_t b = strtol(strings[2], NULL, 16);
-    return (r << 16 | g << 8 | b);
-}
-
 /*
  * Redraws the statusline to the buffer
  *
@@ -309,16 +269,16 @@ void init_colors(const struct xcb_color_strings_t *new_colors) {
     do { \
         colors.name = get_colorpixel(new_colors->name ? new_colors->name : def); \
     } while  (0)
-    PARSE_COLOR(bar_fg, "FFFFFF");
-    PARSE_COLOR(bar_bg, "000000");
-    PARSE_COLOR(active_ws_fg, "FFFFFF");
-    PARSE_COLOR(active_ws_bg, "480000");
-    PARSE_COLOR(inactive_ws_fg, "FFFFFF");
-    PARSE_COLOR(inactive_ws_bg, "240000");
-    PARSE_COLOR(urgent_ws_fg, "FFFFFF");
-    PARSE_COLOR(urgent_ws_bg, "002400");
-    PARSE_COLOR(focus_ws_fg, "FFFFFF");
-    PARSE_COLOR(focus_ws_bg, "480000");
+    PARSE_COLOR(bar_fg, "#FFFFFF");
+    PARSE_COLOR(bar_bg, "#000000");
+    PARSE_COLOR(active_ws_fg, "#FFFFFF");
+    PARSE_COLOR(active_ws_bg, "#333333");
+    PARSE_COLOR(inactive_ws_fg, "#888888");
+    PARSE_COLOR(inactive_ws_bg, "#222222");
+    PARSE_COLOR(urgent_ws_fg, "#FFFFFF");
+    PARSE_COLOR(urgent_ws_bg, "#900000");
+    PARSE_COLOR(focus_ws_fg, "#FFFFFF");
+    PARSE_COLOR(focus_ws_bg, "#285577");
 #undef PARSE_COLOR
 }
 
@@ -414,6 +374,8 @@ static void configure_trayclients() {
 
         int clients = 0;
         TAILQ_FOREACH_REVERSE(trayclient, output->trayclients, tc_head, tailq) {
+            if (!trayclient->mapped)
+                continue;
             clients++;
 
             DLOG("Configuring tray window %08x to x=%d\n",
@@ -537,6 +499,13 @@ static void handle_client_message(xcb_client_message_event_t* event) {
                            (char*)ev);
             free(event);
 
+            /* Put the client inside the save set. Upon termination (whether
+             * killed or normal exit does not matter) of i3bar, these clients
+             * will be correctly reparented to their most closest living
+             * ancestor. Without this, tray icons might die when i3bar
+             * exits/crashes. */
+            xcb_change_save_set(xcb_connection, XCB_SET_MODE_INSERT, client);
+
             if (map_it) {
                 DLOG("Mapping dock client\n");
                 xcb_map_window(xcb_connection, client);
@@ -629,8 +598,10 @@ static void handle_property_notify(xcb_property_notify_event_t *event) {
         xcb_get_property_reply_t *xembedr = xcb_get_property_reply(xcb_connection,
                                                                    xembedc,
                                                                    NULL);
-        if (xembedr == NULL || xembedr->length == 0)
+        if (xembedr == NULL || xembedr->length == 0) {
+            DLOG("xembed_info unset\n");
             return;
+        }
 
         DLOG("xembed format = %d, len = %d\n", xembedr->format, xembedr->length);
         uint32_t *xembed = xcb_get_property_value(xembedr);
@@ -642,11 +613,13 @@ static void handle_property_notify(xcb_property_notify_event_t *event) {
             /* need to unmap the window */
             xcb_unmap_window(xcb_connection, trayclient->win);
             trayclient->mapped = map_it;
+            configure_trayclients();
             draw_bars();
         } else if (!trayclient->mapped && map_it) {
             /* need to map the window */
             xcb_map_window(xcb_connection, trayclient->win);
             trayclient->mapped = map_it;
+            configure_trayclients();
             draw_bars();
         }
         free(xembedr);
@@ -669,6 +642,8 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
 
         int clients = 0;
         TAILQ_FOREACH_REVERSE(trayclient, output->trayclients, tc_head, tailq) {
+            if (!trayclient->mapped)
+                continue;
             clients++;
 
             if (trayclient->win != event->window)
@@ -712,38 +687,37 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
         exit(1);
     }
 
-    while ((event = xcb_poll_for_event(xcb_connection)) == NULL) {
-        return;
-    }
-
-    switch (event->response_type & ~0x80) {
-        case XCB_EXPOSE:
-            /* Expose-events happen, when the window needs to be redrawn */
-            redraw_bars();
-            break;
-        case XCB_BUTTON_PRESS:
-            /* Button-press-events are mouse-buttons clicked on one of our bars */
-            handle_button((xcb_button_press_event_t*) event);
-            break;
-        case XCB_CLIENT_MESSAGE:
-            /* Client messages are used for client-to-client communication, for
-             * example system tray widgets talk to us directly via client messages. */
-            handle_client_message((xcb_client_message_event_t*) event);
-            break;
-        case XCB_UNMAP_NOTIFY:
-            /* UnmapNotifies are received when a tray window unmaps itself */
-            handle_unmap_notify((xcb_unmap_notify_event_t*) event);
-            break;
-        case XCB_PROPERTY_NOTIFY:
-            /* PropertyNotify */
-            handle_property_notify((xcb_property_notify_event_t*) event);
-            break;
-        case XCB_CONFIGURE_REQUEST:
-            /* ConfigureRequest, sent by a tray child */
-            handle_configure_request((xcb_configure_request_event_t*) event);
-            break;
+    while ((event = xcb_poll_for_event(xcb_connection)) != NULL) {
+        switch (event->response_type & ~0x80) {
+            case XCB_EXPOSE:
+                /* Expose-events happen, when the window needs to be redrawn */
+                redraw_bars();
+                break;
+            case XCB_BUTTON_PRESS:
+                /* Button-press-events are mouse-buttons clicked on one of our bars */
+                handle_button((xcb_button_press_event_t*) event);
+                break;
+            case XCB_CLIENT_MESSAGE:
+                /* Client messages are used for client-to-client communication, for
+                 * example system tray widgets talk to us directly via client messages. */
+                handle_client_message((xcb_client_message_event_t*) event);
+                break;
+            case XCB_UNMAP_NOTIFY:
+            case XCB_DESTROY_NOTIFY:
+                /* UnmapNotifies are received when a tray window unmaps itself */
+                handle_unmap_notify((xcb_unmap_notify_event_t*) event);
+                break;
+            case XCB_PROPERTY_NOTIFY:
+                /* PropertyNotify */
+                handle_property_notify((xcb_property_notify_event_t*) event);
+                break;
+            case XCB_CONFIGURE_REQUEST:
+                /* ConfigureRequest, sent by a tray child */
+                handle_configure_request((xcb_configure_request_event_t*) event);
+                break;
+        }
+        free(event);
     }
-    FREE(event);
 }
 
 /*
@@ -811,7 +785,7 @@ char *init_xcb_early() {
     #define ATOM_DO(name) atom_cookies[name] = xcb_intern_atom(xcb_connection, 0, strlen(#name), #name);
     #include "xcb_atoms.def"
 
-    xcb_screen = xcb_setup_roots_iterator(xcb_get_setup(xcb_connection)).data;
+    xcb_screen = xcb_aux_get_screen(xcb_connection, screen);
     xcb_root = xcb_screen->root;
 
     /* We draw the statusline to a seperate pixmap, because it looks the same on all bars and
@@ -897,10 +871,8 @@ char *init_xcb_early() {
  */
 void init_xcb_late(char *fontname) {
     if (fontname == NULL) {
-        /* This is a very restrictive default. More sensefull would be something like
-         * "-misc-*-*-*-*--*-*-*-*-*-*-*-*". But since that produces very ugly results
-         * on my machine, let's stick with this until we have a configfile */
-        fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1";
+        /* XXX: font fallback to 'misc' like i3 does it would be good. */
+        fontname = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1";
     }
 
     /* We load and allocate the font */
@@ -1359,7 +1331,8 @@ void reconfig_windows() {
             }
 
             if (!tray_configured &&
-                strcasecmp("none", config.tray_output) != 0) {
+                (!config.tray_output ||
+                 strcasecmp("none", config.tray_output) != 0)) {
                 init_tray();
                 tray_configured = true;
             }