diff --git a/include/data.h b/include/data.h index b3974a3a..5c4a8852 100644 --- a/include/data.h +++ b/include/data.h @@ -358,6 +358,9 @@ struct Con { TAILQ_ENTRY(Con) focused; TAILQ_ENTRY(Con) all_cons; TAILQ_ENTRY(Con) floating_windows; + + /** callbacks */ + void(*on_remove_child)(Con *); }; #endif diff --git a/include/util.h b/include/util.h index 91b533a1..064a4792 100644 --- a/include/util.h +++ b/include/util.h @@ -34,6 +34,8 @@ } \ while (0) +#define CALL(obj, member, ...) obj->member(obj, ## __VA_ARGS__) + int min(int a, int b); int max(int a, int b); bool rect_contains(Rect rect, uint32_t x, uint32_t y); diff --git a/src/con.c b/src/con.c index c04d281e..65b97443 100644 --- a/src/con.c +++ b/src/con.c @@ -24,6 +24,8 @@ char *colors[] = { "#aa00aa" }; +static void con_on_remove_child(Con *con); + /* * Create a new container (and attach it to the given parent, if not NULL). * This function initializes the data structures and creates the appropriate @@ -32,6 +34,7 @@ char *colors[] = { */ Con *con_new(Con *parent) { Con *new = scalloc(sizeof(Con)); + new->on_remove_child = con_on_remove_child; TAILQ_INSERT_TAIL(&all_cons, new, all_cons); new->type = CT_CON; new->border_style = config.default_border; @@ -522,14 +525,7 @@ void con_move_to_workspace(Con *con, Con *workspace) { /* 8: keep focus on the current workspace */ con_focus(focus_next); - /* 9: check if the parent container is empty now and close it */ - if (parent->type != CT_WORKSPACE && - TAILQ_EMPTY(&(parent->nodes_head))) { - DLOG("Closing empty parent container\n"); - /* TODO: check if this container would swallow any other client and - * don’t close it automatically. */ - tree_close(parent, false, false); - } + CALL(parent, on_remove_child); } /* @@ -744,3 +740,17 @@ void con_set_layout(Con *con, int layout) { con->layout = layout; } + +static void con_on_remove_child(Con *con) { + /* Nothing to do for workspaces */ + if (con->type == CT_WORKSPACE) + return; + + /* TODO: check if this container would swallow any other client and + * don’t close it automatically. */ + DLOG("on_remove_child\n"); + if (con_num_children(con) == 0) { + DLOG("Container empty, closing\n"); + tree_close(con, false, false); + } +} diff --git a/src/tree.c b/src/tree.c index f402aa7d..77da3ac3 100644 --- a/src/tree.c +++ b/src/tree.c @@ -190,14 +190,8 @@ void tree_close(Con *con, bool kill_window, bool dont_kill_parent) { } /* check if the parent container is empty now and close it */ - if (!dont_kill_parent && - parent->type != CT_WORKSPACE && - TAILQ_EMPTY(&(parent->nodes_head))) { - DLOG("Closing empty parent container\n"); - /* TODO: check if this container would swallow any other client and - * don’t close it automatically. */ - tree_close(parent, false, false); - } + if (!dont_kill_parent) + CALL(parent, on_remove_child); } /* @@ -504,6 +498,8 @@ void tree_move(char way, orientation_t orientation) { fix_percent = true; } + CALL(con->parent, on_remove_child); + TAILQ_INSERT_AFTER(&(next->parent->nodes_head), next, con, nodes); TAILQ_INSERT_HEAD(&(next->parent->focus_head), con, focused); /* TODO: don’t influence focus handling? */ @@ -567,13 +563,11 @@ void tree_move(char way, orientation_t orientation) { * container(s) would still point to the old container(s)). */ con_focus(con); - if (con_num_children(old_parent) == 0) { - DLOG("Old container empty after moving. Let's close it\n"); - tree_close(old_parent, false, false); - } else if (level_changed) { - /* fix the percentages in the container we moved from */ + /* fix the percentages in the container we moved from */ + if (level_changed) con_fix_percent(old_parent); - } + + CALL(old_parent, on_remove_child); tree_flatten(croot); }