]> git.sur5r.net Git - i3/i3/blobdiff - libi3/draw_util.c
Move title_format from window to container.
[i3/i3] / libi3 / draw_util.c
index e7e7c09c94f1841aaa9bcab88317be175ce77dd0..dcd881c2de322f9b443cba20151c6f95ee3d521d 100644 (file)
@@ -23,6 +23,14 @@ xcb_visualtype_t *visual_type;
 /* Forward declarations */
 static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surface, color_t color);
 
+#define RETURN_UNLESS_SURFACE_INITIALIZED(surface)                               \
+    do {                                                                         \
+        if ((surface)->id == XCB_NONE) {                                         \
+            ELOG("Surface %p is not initialized, skipping drawing.\n", surface); \
+            return;                                                              \
+        }                                                                        \
+    } while (0)
+
 /*
  * Initialize the surface to represent the given drawable.
  *
@@ -30,7 +38,7 @@ static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surfac
 void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_drawable_t drawable,
                             xcb_visualtype_t *visual, int width, int height) {
     surface->id = drawable;
-    surface->visual_type = (visual == NULL) ? visual_type : visual;
+    surface->visual_type = ((visual == NULL) ? visual_type : visual);
     surface->width = width;
     surface->height = height;
 
@@ -39,8 +47,7 @@ void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_draw
 
     xcb_generic_error_t *error = xcb_request_check(conn, gc_cookie);
     if (error != NULL) {
-        ELOG("Could not create graphical context. Error code: %d\n", error->error_code);
-        exit(EXIT_FAILURE);
+        ELOG("Could not create graphical context. Error code: %d. Please report this bug.\n", error->error_code);
     }
 
 #ifdef CAIRO_SUPPORT
@@ -58,6 +65,12 @@ void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) {
 #ifdef CAIRO_SUPPORT
     cairo_surface_destroy(surface->surface);
     cairo_destroy(surface->cr);
+
+    /* We need to explicitly set these to NULL to avoid assertion errors in
+     * cairo when calling this multiple times. This can happen, for example,
+     * when setting the border of a window to none and then closing it. */
+    surface->surface = NULL;
+    surface->cr = NULL;
 #endif
 }
 
@@ -79,33 +92,37 @@ void draw_util_surface_set_size(surface_t *surface, int width, int height) {
  *
  */
 color_t draw_util_hex_to_color(const char *color) {
-    char groups[3][3] = {
+    char alpha[2];
+    if (strlen(color) == strlen("#rrggbbaa")) {
+        alpha[0] = color[7];
+        alpha[1] = color[8];
+    } else {
+        alpha[0] = alpha[1] = 'F';
+    }
+
+    char groups[4][3] = {
         {color[1], color[2], '\0'},
         {color[3], color[4], '\0'},
-        {color[5], color[6], '\0'}};
+        {color[5], color[6], '\0'},
+        {alpha[0], alpha[1], '\0'}};
 
     return (color_t){
         .red = strtol(groups[0], NULL, 16) / 255.0,
         .green = strtol(groups[1], NULL, 16) / 255.0,
         .blue = strtol(groups[2], NULL, 16) / 255.0,
+        .alpha = strtol(groups[3], NULL, 16) / 255.0,
         .colorpixel = get_colorpixel(color)};
 }
 
-color_t draw_util_colorpixel_to_color(uint32_t colorpixel) {
-    return (color_t){
-        .red = ((colorpixel >> 16) & 0xFF) / 255.0,
-        .green = ((colorpixel >> 8) & 0xFF) / 255.0,
-        .blue = (colorpixel & 0xFF) / 255.0,
-        .colorpixel = colorpixel};
-}
-
 /*
  * Set the given color as the source color on the surface.
  *
  */
 static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surface, color_t color) {
+    RETURN_UNLESS_SURFACE_INITIALIZED(surface);
+
 #ifdef CAIRO_SUPPORT
-    cairo_set_source_rgb(surface->cr, color.red, color.green, color.blue);
+    cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha);
 #else
     uint32_t colorpixel = color.colorpixel;
     xcb_change_gc(conn, surface->gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND,
@@ -120,12 +137,14 @@ static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surfac
  *
  */
 void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width) {
+    RETURN_UNLESS_SURFACE_INITIALIZED(surface);
+
 #ifdef CAIRO_SUPPORT
     /* Flush any changes before we draw the text as this might use XCB directly. */
     CAIRO_SURFACE_FLUSH(surface->surface);
 #endif
 
-    set_font_colors(surface->gc, fg_color.colorpixel, bg_color.colorpixel);
+    set_font_colors(surface->gc, fg_color, bg_color);
     draw_text(text, surface->id, surface->gc, surface->visual_type, x, y, max_width);
 
 #ifdef CAIRO_SUPPORT
@@ -141,6 +160,8 @@ void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_
  *
  */
 void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t color, double x, double y, double w, double h) {
+    RETURN_UNLESS_SURFACE_INITIALIZED(surface);
+
 #ifdef CAIRO_SUPPORT
     cairo_save(surface->cr);
 
@@ -171,6 +192,8 @@ void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t col
  *
  */
 void draw_util_clear_surface(xcb_connection_t *conn, surface_t *surface, color_t color) {
+    RETURN_UNLESS_SURFACE_INITIALIZED(surface);
+
 #ifdef CAIRO_SUPPORT
     cairo_save(surface->cr);
 
@@ -201,6 +224,9 @@ void draw_util_clear_surface(xcb_connection_t *conn, surface_t *surface, color_t
  */
 void draw_util_copy_surface(xcb_connection_t *conn, surface_t *src, surface_t *dest, double src_x, double src_y,
                             double dest_x, double dest_y, double width, double height) {
+    RETURN_UNLESS_SURFACE_INITIALIZED(src);
+    RETURN_UNLESS_SURFACE_INITIALIZED(dest);
+
 #ifdef CAIRO_SUPPORT
     cairo_save(dest->cr);