]> git.sur5r.net Git - i3/i3/blobdiff - src/con.c
Ensure all *.[ch] files include config.h
[i3/i3] / src / con.c
index 24809efbbf99f696f091ba8b67b9b4983d0a6f52..3c7c2186324c55a259914d8f7d700d5a40b39ccf 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -1,5 +1,3 @@
-#undef I3__FILE__
-#define I3__FILE__ "con.c"
 /*
  * vim:ts=4:sw=4:expandtab
  *
@@ -12,6 +10,7 @@
  *
  */
 #include "all.h"
+
 #include "yajl_utils.h"
 
 static void con_on_remove_child(Con *con);
@@ -68,7 +67,7 @@ Con *con_new_skeleton(Con *parent, i3Window *window) {
  */
 Con *con_new(Con *parent, i3Window *window) {
     Con *new = con_new_skeleton(parent, window);
-    x_con_init(new, new->depth);
+    x_con_init(new);
     return new;
 }
 
@@ -608,7 +607,8 @@ void con_mark(Con *con, const char *mark, mark_mode_t mode) {
         DLOG("Removing all existing marks on con = %p.\n", con);
 
         mark_t *current;
-        TAILQ_FOREACH(current, &(con->marks_head), marks) {
+        while (!TAILQ_EMPTY(&(con->marks_head))) {
+            current = TAILQ_FIRST(&(con->marks_head));
             con_unmark(con, current->name);
         }
     }
@@ -726,6 +726,49 @@ int con_num_children(Con *con) {
     return children;
 }
 
+/**
+ * Returns the number of visible non-floating children of this container.
+ * For example, if the container contains a hsplit which has two children,
+ * this will return 2 instead of 1.
+ */
+int con_num_visible_children(Con *con) {
+    if (con == NULL)
+        return 0;
+
+    int children = 0;
+    Con *current = NULL;
+    TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
+        /* Visible leaf nodes are a child. */
+        if (!con_is_hidden(current) && con_is_leaf(current))
+            children++;
+        /* All other containers need to be recursed. */
+        else
+            children += con_num_visible_children(current);
+    }
+
+    return children;
+}
+
+/*
+ * Count the number of windows (i.e., leaf containers).
+ *
+ */
+int con_num_windows(Con *con) {
+    if (con == NULL)
+        return 0;
+
+    if (con_has_managed_window(con))
+        return 1;
+
+    int num = 0;
+    Con *current = NULL;
+    TAILQ_FOREACH(current, &(con->nodes_head), nodes) {
+        num += con_num_windows(current);
+    }
+
+    return num;
+}
+
 /*
  * Updates the percent attribute of the children of the given container. This
  * function needs to be called when a window is added or removed from a
@@ -1079,6 +1122,7 @@ static bool _con_move_to_con(Con *con, Con *target, bool behind_focused, bool fi
     CALL(parent, on_remove_child);
 
     ipc_send_window_event("move", con);
+    ewmh_update_wm_desktop();
     return true;
 }
 
@@ -1155,6 +1199,19 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
     _con_move_to_con(con, target, true, fix_coordinates, dont_warp, ignore_focus);
 }
 
+/*
+ * Moves the given container to the currently focused container on the
+ * visible workspace on the given output.
+ *
+ */
+void con_move_to_output(Con *con, Output *output) {
+    Con *ws = NULL;
+    GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child));
+    assert(ws != NULL);
+    DLOG("Moving con %p to output %s\n", con, output->name);
+    con_move_to_workspace(con, ws, false, false, false);
+}
+
 /*
  * Returns the orientation of the given container (for stacked containers,
  * vertical orientation is used regardless of the actual orientation of the
@@ -1409,6 +1466,12 @@ Con *con_descend_direction(Con *con, direction_t direction) {
  *
  */
 Rect con_border_style_rect(Con *con) {
+    if (config.hide_edge_borders == HEBM_SMART && con_num_visible_children(con_get_workspace(con)) <= 1) {
+        if (!con_is_floating(con)) {
+            return (Rect){0, 0, 0, 0};
+        }
+    }
+
     adjacent_t borders_to_hide = ADJ_NONE;
     int border_width = con->current_border_width;
     DLOG("The border width for con is set to: %d\n", con->current_border_width);
@@ -1884,6 +1947,13 @@ bool con_has_urgent_child(Con *con) {
 void con_update_parents_urgency(Con *con) {
     Con *parent = con->parent;
 
+    /* Urgency hints should not be set on any container higher up in the
+     * hierarchy than the workspace level. Unfortunately, since the content
+     * container has type == CT_CON, that’s not easy to verify in the loop
+     * below, so we need another condition to catch that case: */
+    if (con->type == CT_WORKSPACE)
+        return;
+
     bool new_urgency_value = con->urgent;
     while (parent && parent->type != CT_WORKSPACE && parent->type != CT_DOCKAREA) {
         if (new_urgency_value) {
@@ -1991,6 +2061,7 @@ char *con_get_tree_representation(Con *con) {
                   (TAILQ_FIRST(&(con->nodes_head)) == child ? "" : " "), child_txt);
         free(buf);
         buf = tmp_buf;
+        free(child_txt);
     }
 
     /* 3) close the brackets */
@@ -2000,3 +2071,47 @@ char *con_get_tree_representation(Con *con) {
 
     return complete_buf;
 }
+
+/*
+ * Returns the container's title considering the current title format.
+ *
+ */
+i3String *con_parse_title_format(Con *con) {
+    assert(con->title_format != NULL);
+
+    i3Window *win = con->window;
+
+    /* We need to ensure that we only escape the window title if pango
+     * is used by the current font. */
+    const bool pango_markup = font_is_pango();
+
+    char *title;
+    char *class;
+    char *instance;
+    if (win == NULL) {
+        title = pango_escape_markup(con_get_tree_representation(con));
+        class = sstrdup("i3-frame");
+        instance = sstrdup("i3-frame");
+    } else {
+        title = pango_escape_markup(sstrdup((win->name == NULL) ? "" : i3string_as_utf8(win->name)));
+        class = pango_escape_markup(sstrdup((win->class_class == NULL) ? "" : win->class_class));
+        instance = pango_escape_markup(sstrdup((win->class_instance == NULL) ? "" : win->class_instance));
+    }
+
+    placeholder_t placeholders[] = {
+        {.name = "%title", .value = title},
+        {.name = "%class", .value = class},
+        {.name = "%instance", .value = instance}};
+    const size_t num = sizeof(placeholders) / sizeof(placeholder_t);
+
+    char *formatted_str = format_placeholders(con->title_format, &placeholders[0], num);
+    i3String *formatted = i3string_from_utf8(formatted_str);
+    i3string_set_markup(formatted, pango_markup);
+    FREE(formatted_str);
+
+    for (size_t i = 0; i < num; i++) {
+        FREE(placeholders[i].value);
+    }
+
+    return formatted;
+}