From 70d06f7888337836e1811cc726c47f1fabc16c5e Mon Sep 17 00:00:00 2001 From: Akos Horvath Date: Fri, 29 Dec 2023 19:08:58 +0100 Subject: [PATCH] rewrite NodeArray: use heap allocated struct pointer, remove unused ClientArray functions --- src/client.c | 26 ++-- src/tests.c | 270 +++++++++++++++++++++-------------- src/util.c | 386 +++++++++++++++------------------------------------ src/util.h | 35 ++--- src/wm.c | 42 +++--- 5 files changed, 322 insertions(+), 437 deletions(-) diff --git a/src/client.c b/src/client.c index fe654db..53b0dff 100644 --- a/src/client.c +++ b/src/client.c @@ -41,11 +41,11 @@ XWindowChanges wm_client_to_xwchanges(Client *c) Client* wm_client_find(Wm *wm, Window w) { - PtrArray clients = wm_treenode_find_client_nodes_ptr(wm->smon->workspaces[wm->smon->selws].tree); + NodeArray *clients = wm_treenode_find_client_nodes(CURRENT_WS(wm).tree); Client *ret = NULL; - for (size_t i = 0; i < clients.size; i++) { - Client *c = ((TreeNode*)clients.ptrs[i])->client; + for (size_t i = 0; i < clients->size; i++) { + Client *c = ((TreeNode*)clients->nodes[i])->client; if (c->window == w) { ret = c; goto ret; @@ -53,7 +53,7 @@ Client* wm_client_find(Wm *wm, Window w) } ret: - wm_ptrarray_free(&clients); + wm_nodearray_free(clients); return ret; } @@ -367,7 +367,7 @@ Client* wm_client_get_dir_rel_c(Client *c, int dir) return NULL; } - PtrArray client_nodes = wm_treenode_find_client_nodes_ptr(c->ws->tree); + NodeArray *client_nodes = wm_treenode_find_client_nodes(c->ws->tree); x+=dx*5; y+=dy*5; @@ -375,8 +375,8 @@ Client* wm_client_get_dir_rel_c(Client *c, int dir) x+=dx*2; y+=dy*2; - for (size_t i = 0; i < client_nodes.size; i++) { - Client *r = ((TreeNode**)client_nodes.ptrs)[i]->client; + for (size_t i = 0; i < client_nodes->size; i++) { + Client *r = ((TreeNode**)client_nodes->nodes)[i]->client; if ((x > r->x && x < r->x+r->w) && (y > r->y && y < r->y+r->h)) { DEBUG_PRINT("%s ", __func__) DEBUG_PRINT("found window %d in direction ", (int)c->window) @@ -390,7 +390,7 @@ Client* wm_client_get_dir_rel_c(Client *c, int dir) (y > 0 && y < c->m->info.height)); ret: - wm_ptrarray_free(&client_nodes); + wm_nodearray_free(client_nodes); DEBUG_PRINT("%s returning %p\n", __func__, (void*)ret); return ret; } @@ -438,18 +438,18 @@ void wm_monitor_clients_border(Wm *wm, Monitor *m) { DEBUG_PRINT("%s\n", __func__) RETURN_IF_NULL(m); - PtrArray clients = wm_treenode_find_client_nodes_ptr(m->workspaces[m->selws].tree); - if (clients.size == 0) + NodeArray *clients = wm_treenode_find_client_nodes(m->workspaces[m->selws].tree); + if (clients->size == 0) return; - for (size_t i = 0; i < clients.size; i++) { - Client *client = ((TreeNode*)clients.ptrs[i])->client; + for (size_t i = 0; i < clients->size; i++) { + Client *client = ((TreeNode*)clients->nodes[i])->client; DEBUG_PRINT("monitor border c: %p\n", (void*)client) DEBUG_PRINT("monitor border c window: %ld\n", client->window) wm_client_border(wm, client); } - wm_ptrarray_free(&clients); + wm_nodearray_free(clients); } bool wm_client_is_focused(Wm *wm, Client *c) diff --git a/src/tests.c b/src/tests.c index 601cf5c..07c5721 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7,18 +7,7 @@ // store a copy of the nodes created in test2_setup, to check if any // of the tests modified them -static PtrArray test_group2_nodes_copy = {0}; - -static void test_wm_treenode_new(void **state) -{ - TreeNode *node = wm_treenode_new(NODE_VERTICAL, NULL); - assert_null(node->client); - assert_non_null(node->children.nodes); - assert_int_equal(node->children.size, 0); - assert_int_equal(node->type, NODE_VERTICAL); - - wm_treenode_free(node); -} +static NodeArray *test_group2_nodes_copy = NULL; static void test_wm_nodearray_push(void **state) { @@ -30,51 +19,90 @@ static void test_wm_nodearray_push(void **state) assert_null(node->parent); assert_ptr_equal(node1->parent, node); - wm_nodearray_push(&node->children, node1); + wm_nodearray_push(node->children, node1); - assert_int_equal(node->children.size, 1); - assert_ptr_equal(node->children.nodes[0], node1); + assert_int_equal(node->children->size, 1); + assert_ptr_equal(node->children->nodes[0], node1); assert_int_equal(node1->id, 123); - assert_int_equal(node->children.nodes[0]->id, 123); + assert_int_equal(node->children->nodes[0]->id, 123); wm_treenode_free(node); wm_treenode_free(node1); } -static void test_wm_find_client_nodes_ptr(void **state) +static void test_wm_treenode_new(void **state) { - TreeNode *root = wm_treenode_new(NODE_VERTICAL, NULL); - TreeNode *node1 = wm_treenode_new(NODE_CLIENT, NULL); - TreeNode *node2 = wm_treenode_new(NODE_CLIENT, NULL); + TreeNode *node = wm_treenode_new(NODE_VERTICAL, NULL); + assert_null(node->client); + assert_non_null(node->children->nodes); + assert_int_equal(node->children->size, 0); + assert_int_equal(node->type, NODE_VERTICAL); - node1->client = (Client*)0x123; - node2->client = (Client*)0x456; - - const unsigned long ids[] = {123, 456}; - - node1->id = ids[0]; - node2->id = ids[1]; - - wm_nodearray_push(&root->children, node1); - wm_nodearray_push(&root->children, node2); - - assert_int_equal(root->children.size, 2); - assert_ptr_equal(root->children.nodes[0], node1); - assert_ptr_equal(root->children.nodes[1], node2); - - PtrArray client_ptrs = wm_treenode_find_client_nodes_ptr(root); - - assert_int_equal(client_ptrs.size, 2); - assert_in_set(((TreeNode*)client_ptrs.ptrs[0])->id, ids, 2); - assert_in_set(((TreeNode*)client_ptrs.ptrs[1])->id, ids, 2); - - wm_treenode_free(root); - wm_treenode_free(node1); - wm_treenode_free(node2); - wm_ptrarray_free(&client_ptrs); + wm_treenode_free(node); } -static void test_wm_all_nodes_to_ptrarray(void **state) +static void test_wm_treenode_split_space(void **state) +{ + /* vertical */ + TreeNode *parent = wm_treenode_new(NODE_VERTICAL, NULL); + + parent->pos.x = 0; + parent->pos.y = 0; + parent->pos.w = 200; + parent->pos.h = 200; + + TreeNode *child1 = wm_treenode_new(NODE_CLIENT, parent); + TreeNode *child2 = wm_treenode_new(NODE_CLIENT, parent); + + wm_treenode_split_space(parent, &child1->pos, &child2->pos); + + assert_int_equal(child1->pos.x, 0); + assert_int_equal(child1->pos.y, 0); + + assert_int_equal(child1->pos.w, 100); + assert_int_equal(child1->pos.h, 200); + + assert_int_equal(child2->pos.x, 100); + assert_int_equal(child2->pos.y, 0); + + assert_int_equal(child2->pos.w, 100); + assert_int_equal(child2->pos.h, 200); + + wm_treenode_free(parent); + wm_treenode_free(child1); + wm_treenode_free(child2); + + /* horizontal */ + parent = wm_treenode_new(NODE_HORIZONTAL, NULL); + + parent->pos.x = 0; + parent->pos.y = 0; + parent->pos.w = 200; + parent->pos.h = 200; + + child1 = wm_treenode_new(NODE_CLIENT, parent); + child2 = wm_treenode_new(NODE_CLIENT, parent); + + wm_treenode_split_space(parent, &child1->pos, &child2->pos); + + assert_int_equal(child1->pos.x, 0); + assert_int_equal(child1->pos.y, 0); + + assert_int_equal(child1->pos.w, 200); + assert_int_equal(child1->pos.h, 100); + + assert_int_equal(child2->pos.x, 0); + assert_int_equal(child2->pos.y, 100); + + assert_int_equal(child2->pos.w, 200); + assert_int_equal(child2->pos.h, 100); + + wm_treenode_free(parent); + wm_treenode_free(child1); + wm_treenode_free(child2); +} + +static void test_wm_all_nodes_to_array(void **state) { TreeNode *root = wm_treenode_new(NODE_VERTICAL, NULL); TreeNode *node1 = wm_treenode_new(NODE_CLIENT, NULL); @@ -88,28 +116,61 @@ static void test_wm_all_nodes_to_ptrarray(void **state) node2->id = ids[2]; node3->id = ids[3]; - wm_nodearray_push(&root->children, node1); - wm_nodearray_push(&root->children, node2); - wm_nodearray_push(&root->children, node3); + wm_nodearray_push(root->children, node1); + wm_nodearray_push(root->children, node2); + wm_nodearray_push(root->children, node3); - assert_int_equal(root->children.size, 3); - assert_ptr_equal(root->children.nodes[0], node1); - assert_ptr_equal(root->children.nodes[1], node2); - assert_ptr_equal(root->children.nodes[2], node3); + assert_int_equal(root->children->size, 3); + assert_ptr_equal(root->children->nodes[0], node1); + assert_ptr_equal(root->children->nodes[1], node2); + assert_ptr_equal(root->children->nodes[2], node3); - PtrArray all_nodes = wm_all_nodes_to_ptrarray(root); + NodeArray *all_nodes = wm_all_nodes_to_array(root); - assert_int_equal(all_nodes.size, 4); - assert_in_set(((TreeNode*)all_nodes.ptrs[0])->id, ids, 4); - assert_in_set(((TreeNode*)all_nodes.ptrs[1])->id, ids, 4); - assert_in_set(((TreeNode*)all_nodes.ptrs[2])->id, ids, 4); - assert_in_set(((TreeNode*)all_nodes.ptrs[3])->id, ids, 4); + assert_int_equal(all_nodes->size, 4); + assert_in_set(((TreeNode*)all_nodes->nodes[0])->id, ids, 4); + assert_in_set(((TreeNode*)all_nodes->nodes[1])->id, ids, 4); + assert_in_set(((TreeNode*)all_nodes->nodes[2])->id, ids, 4); + assert_in_set(((TreeNode*)all_nodes->nodes[3])->id, ids, 4); wm_treenode_free(root); wm_treenode_free(node1); wm_treenode_free(node2); wm_treenode_free(node3); - wm_ptrarray_free(&all_nodes); + wm_nodearray_free(all_nodes); +} + +static void test_wm_find_client_nodes(void **state) +{ + TreeNode *root = wm_treenode_new(NODE_VERTICAL, NULL); + TreeNode *node1 = wm_treenode_new(NODE_CLIENT, NULL); + TreeNode *node2 = wm_treenode_new(NODE_CLIENT, NULL); + + node1->client = (Client*)0x123; + node2->client = (Client*)0x456; + + const unsigned long ids[] = {123, 456}; + + node1->id = ids[0]; + node2->id = ids[1]; + + wm_nodearray_push(root->children, node1); + wm_nodearray_push(root->children, node2); + + assert_int_equal(root->children->size, 2); + assert_ptr_equal(root->children->nodes[0], node1); + assert_ptr_equal(root->children->nodes[1], node2); + + NodeArray *client_nodes = wm_treenode_find_client_nodes(root); + + assert_int_equal(client_nodes->size, 2); + assert_in_set((client_nodes->nodes[0])->id, ids, 2); + assert_in_set((client_nodes->nodes[1])->id, ids, 2); + + wm_treenode_free(root); + wm_treenode_free(node1); + wm_treenode_free(node2); + wm_nodearray_free(client_nodes); } static void test_wm_postorder_traversal(void **state) @@ -136,13 +197,13 @@ static void test_wm_postorder_traversal(void **state) static void test_wm_treenode_lmd(void **state) { TreeNode *node1 = (TreeNode*)*state; - TreeNode *node2 = node1->children.nodes[0]; - TreeNode *node3 = node1->children.nodes[1]; - TreeNode *node4 = node2->children.nodes[0]; - TreeNode *node5 = node2->children.nodes[1]; - TreeNode *node6 = node2->children.nodes[2]; - TreeNode *node7 = node3->children.nodes[0]; - TreeNode *node8 = node3->children.nodes[1]; + TreeNode *node2 = node1->children->nodes[0]; + TreeNode *node3 = node1->children->nodes[1]; + TreeNode *node4 = node2->children->nodes[0]; + TreeNode *node5 = node2->children->nodes[1]; + TreeNode *node6 = node2->children->nodes[2]; + TreeNode *node7 = node3->children->nodes[0]; + TreeNode *node8 = node3->children->nodes[1]; assert_int_equal(wm_treenode_lmd(node1)->id, node4->id); assert_int_equal(wm_treenode_lmd(node2)->id, node4->id); @@ -225,13 +286,13 @@ static int test2_setup(void **state) TreeNode *node7 = wm_treenode_new(NODE_VERTICAL, node3); TreeNode *node8 = wm_treenode_new(NODE_VERTICAL, node3); - wm_nodearray_push(&node1->children, node2); - wm_nodearray_push(&node1->children, node3); - wm_nodearray_push(&node2->children, node4); - wm_nodearray_push(&node2->children, node5); - wm_nodearray_push(&node2->children, node6); - wm_nodearray_push(&node3->children, node7); - wm_nodearray_push(&node3->children, node8); + wm_nodearray_push(node1->children, node2); + wm_nodearray_push(node1->children, node3); + wm_nodearray_push(node2->children, node4); + wm_nodearray_push(node2->children, node5); + wm_nodearray_push(node2->children, node6); + wm_nodearray_push(node3->children, node7); + wm_nodearray_push(node3->children, node8); node1->id = 1; node2->id = 2; @@ -251,54 +312,54 @@ static int test2_setup(void **state) assert_ptr_equal(node7->parent, node3); assert_ptr_equal(node8->parent, node3); - assert_int_equal(node1->children.size, 2); - assert_int_equal(node2->children.size, 3); - assert_int_equal(node3->children.size, 2); + assert_int_equal(node1->children->size, 2); + assert_int_equal(node2->children->size, 3); + assert_int_equal(node3->children->size, 2); assert_int_equal(node1->id, 1); - assert_int_equal(node1->children.nodes[0]->id, 2); - assert_int_equal(node1->children.nodes[1]->id, 3); - assert_int_equal(node2->children.nodes[0]->id, 4); - assert_int_equal(node2->children.nodes[1]->id, 5); - assert_int_equal(node2->children.nodes[2]->id, 6); - assert_int_equal(node3->children.nodes[0]->id, 7); - assert_int_equal(node3->children.nodes[1]->id, 8); + assert_int_equal(node1->children->nodes[0]->id, 2); + assert_int_equal(node1->children->nodes[1]->id, 3); + assert_int_equal(node2->children->nodes[0]->id, 4); + assert_int_equal(node2->children->nodes[1]->id, 5); + assert_int_equal(node2->children->nodes[2]->id, 6); + assert_int_equal(node3->children->nodes[0]->id, 7); + assert_int_equal(node3->children->nodes[1]->id, 8); *state = node1; - PtrArray nodes = wm_all_nodes_to_ptrarray((TreeNode*)*state); + NodeArray *nodes = wm_all_nodes_to_array((TreeNode*)*state); - PtrArray nodes_copy = wm_ptrarray_new(); - for (size_t i = 0; i < nodes.size; i++) { + test_group2_nodes_copy = wm_nodearray_new(); + for (size_t i = 0; i < nodes->size; i++) { TreeNode *node_copy = malloc(sizeof(TreeNode)); - *node_copy = *((TreeNode**)nodes.ptrs)[i]; - wm_ptrarray_push(&nodes_copy, node_copy); + *node_copy = *(nodes->nodes)[i]; + wm_nodearray_push(test_group2_nodes_copy, node_copy); } - test_group2_nodes_copy = nodes_copy; - - wm_ptrarray_free(&nodes); + wm_nodearray_free(nodes); return 0; } static int test2_teardown(void **state) { - PtrArray nodes = wm_all_nodes_to_ptrarray((TreeNode*)*state); + NodeArray *nodes = wm_all_nodes_to_array((TreeNode*)*state); + + assert_non_null(test_group2_nodes_copy); // check if any of the original nodes were modified - for (size_t i = 0; i < test_group2_nodes_copy.size; i++) { - TreeNode *node_copy = ((TreeNode**)test_group2_nodes_copy.ptrs)[i]; - assert_memory_equal(node_copy, nodes.ptrs[i], sizeof(TreeNode)); + for (size_t i = 0; i < test_group2_nodes_copy->size; i++) { + TreeNode *node_copy = ((TreeNode**)test_group2_nodes_copy->nodes)[i]; + assert_memory_equal(node_copy, nodes->nodes[i], sizeof(TreeNode)); } - for (size_t i = 0; i < nodes.size; i++) { - wm_treenode_free(nodes.ptrs[i]); - free((TreeNode*)test_group2_nodes_copy.ptrs[i]); + for (size_t i = 0; i < nodes->size; i++) { + wm_treenode_free(nodes->nodes[i]); + free((TreeNode*)test_group2_nodes_copy->nodes[i]); } - wm_ptrarray_free(&nodes); - wm_ptrarray_free(&test_group2_nodes_copy); + wm_nodearray_free(nodes); + wm_nodearray_free(test_group2_nodes_copy); return 0; } @@ -306,10 +367,11 @@ static int test2_teardown(void **state) int main(void) { const struct CMUnitTest test_group1[] = { - cmocka_unit_test(test_wm_treenode_new), cmocka_unit_test(test_wm_nodearray_push), - cmocka_unit_test(test_wm_find_client_nodes_ptr), - cmocka_unit_test(test_wm_all_nodes_to_ptrarray), + cmocka_unit_test(test_wm_treenode_new), + cmocka_unit_test(test_wm_treenode_split_space), + cmocka_unit_test(test_wm_all_nodes_to_array), + cmocka_unit_test(test_wm_find_client_nodes), }; const struct CMUnitTest test_group2[] = { diff --git a/src/util.c b/src/util.c index 7204b58..2c9ea0c 100644 --- a/src/util.c +++ b/src/util.c @@ -29,15 +29,15 @@ TreeNode* wm_treenode_new(NodeType type, TreeNode *parent) void wm_treenode_free(TreeNode *node) { - wm_nodearray_clear(&node->children); - __wm_nodearray_free(&node->children); + wm_nodearray_clear(node->children); + wm_nodearray_free(node->children); free(node); } bool wm_treenode_is_empty(TreeNode *node) { DEBUG_PRINT("%s\n", __func__); - return (node->children.size == 0); + return (node->children->size == 0); } void wm_treenode_split_space(TreeNode *node, Rect *ret1, Rect *ret2) @@ -83,10 +83,10 @@ void wm_treenode_recalculate_space(TreeNode *node) { assert(node); - assert(node->children.size == 2); + assert(node->children->size == 2); - wm_treenode_split_space(node, &node->children.nodes[0]->pos, - &node->children.nodes[1]->pos); + wm_treenode_split_space(node, &node->children->nodes[0]->pos, + &node->children->nodes[1]->pos); } void wm_treenode_swap(TreeNode *root, TreeNode *node1, TreeNode* node2) @@ -135,8 +135,8 @@ char* wm_treenode_to_str(TreeNode *node) json_object_object_add(jobj, "parent", json_object_new_uint64((uint64_t)node->parent)); json_object_object_add(jobj, "children", json_object_new_array()); - for (size_t i = 0; i < node->children.size; i++) { - char *child_str = wm_treenode_to_str(node->children.nodes[i]); + for (size_t i = 0; i < node->children->size; i++) { + char *child_str = wm_treenode_to_str(node->children->nodes[i]); json_object_array_add(json_object_object_get(jobj, "children"), json_tokener_parse(child_str)); free(child_str); @@ -225,9 +225,9 @@ TreeNode* wm_treenode_lmd(TreeNode *node) { assert(node); - if (node->children.size == 0) return node; + if (node->children->size == 0) return node; - return wm_treenode_lmd(node->children.nodes[0]); + return wm_treenode_lmd(node->children->nodes[0]); } PtrArray wm_treenode_all_lmds(TreeNode *node) @@ -271,8 +271,8 @@ PtrArray wm_postorder_traversal(TreeNode *tree) wm_ptrarray_push(&stack, n); root_index = 0; - if (root->children.size >= 1) - root = root->children.nodes[0]; + if (root->children->size >= 1) + root = root->children->nodes[0]; else root = NULL; continue; @@ -285,7 +285,7 @@ PtrArray wm_postorder_traversal(TreeNode *tree) wm_ptrarray_push(&ret, n.node); while (stack.size > 0 && n.index == ((NodeWithIndex**)stack.ptrs) - [stack.size-1]->node->children.size - 1) { + [stack.size-1]->node->children->size - 1) { wm_ptrarray_pop(&stack, (void**)&nptr); n = *nptr; free(nptr); @@ -295,7 +295,7 @@ PtrArray wm_postorder_traversal(TreeNode *tree) if (stack.size > 0) { root = ((NodeWithIndex**)stack.ptrs)[stack.size-1]->node - ->children.nodes[n.index + 1]; + ->children->nodes[n.index + 1]; root_index = n.index + 1; } } @@ -346,36 +346,36 @@ void wm_tree_to_DOT(TreeNode *root, const char *filename) fprintf(fp, "digraph {\n"); - PtrArray all_nodes = wm_all_nodes_to_ptrarray(root); - NodeArray printed_nodes = wm_nodearray_new(); + NodeArray *all_nodes = wm_all_nodes_to_array(root); + NodeArray *printed_nodes = wm_nodearray_new(); const int bufsize = 100; char buf1[bufsize]; char buf2[bufsize]; - for (size_t i = 0; i < all_nodes.size; i++) { - TreeNode *node = all_nodes.ptrs[i]; + for (size_t i = 0; i < all_nodes->size; i++) { + TreeNode *node = all_nodes->nodes[i]; bool contains = false; - for (size_t j = 0; j < printed_nodes.size; j++) { - if (printed_nodes.nodes[j]->id == node->id) + for (size_t j = 0; j < printed_nodes->size; j++) { + if (printed_nodes->nodes[j]->id == node->id) contains = true; } if (contains) continue; - for (size_t j = 0; j < node->children.size; j++) { + for (size_t j = 0; j < node->children->size; j++) { memset(buf1, 0, bufsize); memset(buf2, 0, bufsize); wm_node_type_to_str(node->type, buf1, bufsize); - wm_node_type_to_str(node->children.nodes[j]->type, buf2, bufsize); + wm_node_type_to_str(node->children->nodes[j]->type, buf2, bufsize); fprintf(fp, "_%d_%s -> _%d_%s;\n", node->id, buf1, - node->children.nodes[j]->id, buf2); + node->children->nodes[j]->id, buf2); } - wm_nodearray_push(&printed_nodes, node); + wm_nodearray_push(printed_nodes, node); } fprintf(fp, "}"); @@ -383,14 +383,14 @@ void wm_tree_to_DOT(TreeNode *root, const char *filename) fflush(fp); fclose(fp); - __wm_nodearray_free(&printed_nodes); - wm_ptrarray_free(&all_nodes); + wm_nodearray_free(printed_nodes); + wm_nodearray_free(all_nodes); } int wm_get_node_index(TreeNode *parent, unsigned int node_id) { - for (size_t i = 0; i < parent->children.size; i++) { - if (node_id == parent->children.nodes[i]->id) + for (size_t i = 0; i < parent->children->size; i++) { + if (node_id == parent->children->nodes[i]->id) return i; } @@ -412,15 +412,15 @@ void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node) return; } - for (size_t i = 0; i < parent->children.size; i++) { - if (parent->children.nodes[i]->type == NODE_CLIENT && - parent->children.nodes[i] != node) { + for (size_t i = 0; i < parent->children->size; i++) { + if (parent->children->nodes[i]->type == NODE_CLIENT && + parent->children->nodes[i] != node) { parent->type = NODE_CLIENT; - parent->client = parent->children.nodes[i]->client; + parent->client = parent->children->nodes[i]->client; wm_treenode_free(node); - wm_treenode_free(parent->children.nodes[i]); - wm_nodearray_clear(&parent->children); + wm_treenode_free(parent->children->nodes[i]); + wm_nodearray_clear(parent->children); return; } } @@ -448,28 +448,28 @@ void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node) .h = node->client->ws->monitor->info.height - wm->config.border_width*2 - dock_y, }; - assert(node->client->ws->tree->children.size == 2); - wm_treenode_split_space(node->client->ws->tree, &node->client->ws->tree->children.nodes[0]->pos, - &node->client->ws->tree->children.nodes[1]->pos); + assert(node->client->ws->tree->children->size == 2); + wm_treenode_split_space(node->client->ws->tree, &node->client->ws->tree->children->nodes[0]->pos, + &node->client->ws->tree->children->nodes[1]->pos); } else { sibling_node->parent = parent->parent; *parent = *sibling_node; - for (size_t i = 0; i < parent->children.size; i++) { - parent->children.nodes[i]->parent = parent; + for (size_t i = 0; i < parent->children->size; i++) { + parent->children->nodes[i]->parent = parent; } wm_treenode_recalculate_space(parent->parent); wm_treenode_recalculate_space(parent); } - assert(node->client->ws->tree->children.size >= 1); + assert(node->client->ws->tree->children->size >= 1); } TreeNode* wm_treenode_split_get_sibling(TreeNode *node) { - for (size_t i = 0; i < node->parent->children.size; i++) { - TreeNode *sibling_node = node->parent->children.nodes[i]; + for (size_t i = 0; i < node->parent->children->size; i++) { + TreeNode *sibling_node = node->parent->children->nodes[i]; if (sibling_node->id != node->id) { return sibling_node; } @@ -492,15 +492,15 @@ TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client) TreeNode *node = client_node->parent; - for (size_t i = 0; i < node->children.size; i++) { - if (node->children.nodes[i]->type == NODE_CLIENT && - node->children.nodes[i]->client != client) { + for (size_t i = 0; i < node->children->size; i++) { + if (node->children->nodes[i]->type == NODE_CLIENT && + node->children->nodes[i]->client != client) { node->type = NODE_CLIENT; - node->client = node->children.nodes[i]->client; + node->client = node->children->nodes[i]->client; wm_treenode_free(client_node); - wm_treenode_free(node->children.nodes[i]); - wm_nodearray_clear(&node->children); + wm_treenode_free(node->children->nodes[i]); + wm_nodearray_clear(node->children); return node; } } @@ -527,32 +527,32 @@ TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client) .h = client->ws->monitor->info.height - wm->config.border_width*2 - dock_y, }; - assert(client->ws->tree->children.size == 2); - wm_treenode_split_space(client->ws->tree, &client->ws->tree->children.nodes[0]->pos, - &client->ws->tree->children.nodes[1]->pos); + assert(client->ws->tree->children->size == 2); + wm_treenode_split_space(client->ws->tree, &client->ws->tree->children->nodes[0]->pos, + &client->ws->tree->children->nodes[1]->pos); } else { sibling_node->parent = node->parent; *node = *sibling_node; - for (size_t i = 0; i < node->children.size; i++) { - node->children.nodes[i]->parent = node; + for (size_t i = 0; i < node->children->size; i++) { + node->children->nodes[i]->parent = node; } wm_treenode_recalculate_space(node->parent); wm_treenode_recalculate_space(node); } - assert(client->ws->tree->children.size >= 1); - return node->children.nodes[0]; + assert(client->ws->tree->children->size >= 1); + return node->children->nodes[0]; } -NodeArray wm_nodearray_new() +NodeArray* wm_nodearray_new() { - NodeArray arr; + NodeArray *arr = calloc(1, sizeof(NodeArray)); - arr.capacity = 10; - arr.nodes = calloc(arr.capacity, sizeof(TreeNode*)); - arr.size = 0; + arr->capacity = 10; + arr->nodes = calloc(arr->capacity, sizeof(TreeNode*)); + arr->size = 0; return arr; } @@ -581,7 +581,7 @@ void wm_nodearray_push(NodeArray *arr, TreeNode *node) arr->nodes[arr->size - 1] = node; } -bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret) +bool wm_nodearray_pop(NodeArray *arr, TreeNode **ret) { DEBUG_PRINT("%s\n", __func__); assert(arr); @@ -590,12 +590,12 @@ bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret) if (arr->size == 0) return false; - ret = arr->nodes[arr->size - 1]; + *ret = arr->nodes[arr->size - 1]; arr->size--; return true; } -bool wm_nodearray_pop_front(NodeArray *arr, TreeNode *ret) +bool wm_nodearray_pop_front(NodeArray *arr, TreeNode **ret) { assert(arr); assert(ret); @@ -603,7 +603,7 @@ bool wm_nodearray_pop_front(NodeArray *arr, TreeNode *ret) if (arr->size == 0) return false; - ret = arr->nodes[0]; + *ret = arr->nodes[0]; arr->size--; memmove(arr->nodes, arr->nodes+1, arr->size * sizeof(TreeNode*)); @@ -638,63 +638,14 @@ bool wm_nodearray_remove(NodeArray *arr, size_t index) return true; } -void __wm_nodearray_free(NodeArray *arr) +void wm_nodearray_free(NodeArray *arr) { - // DEBUG_PRINT("%s\n", __func__); assert(arr); arr->capacity = 0; arr->size = 0; free(arr->nodes); -} - -// breadth-first search for finding client nodes in tree -ClientArray wm_nodearray_find_clients(TreeNode *root) -{ - DEBUG_PRINT("%s\n", __func__); - assert(root); - - /* storing visited nodes in an array and searching is - not optimal, but this is not a performance-critical function. */ - NodeArray visited = wm_nodearray_new(); - wm_nodearray_push(&visited, root); - - NodeArray queue = wm_nodearray_new(); - ClientArray clients = wm_clientarray_new(); - - wm_nodearray_push(&queue, root); - - while (queue.size > 0) { - TreeNode node; - - if (!wm_nodearray_pop_front(&queue, &node)) - goto ret; - - if (node.type == NODE_CLIENT) - wm_clientarray_push(&clients, *node.client); - - for (size_t i = 0; i < node.children.size; i++) { - TreeNode *child_node = node.children.nodes[i]; - bool _visited = false; - - for (size_t j = 0; j < visited.size; j++) { - if (visited.nodes[j]->id == child_node->id) { - _visited = true; - break; - } - } - - if (!_visited) { - wm_nodearray_push(&visited, child_node); - wm_nodearray_push(&queue, child_node); - } - } - } - -ret: - __wm_nodearray_free(&visited); - __wm_nodearray_free(&queue); - return clients; + free(arr); } PtrArray wm_ptrarray_new() @@ -801,8 +752,8 @@ TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root) TreeNode *ret = NULL; - NodeArray visited = wm_nodearray_new(); - wm_nodearray_push(&visited, root); + NodeArray *visited = wm_nodearray_new(); + wm_nodearray_push(visited, root); PtrArray queue = wm_ptrarray_new(); @@ -819,26 +770,26 @@ TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root) goto ret; } - for (size_t i = 0; i < node->children.size; i++) { - TreeNode *child_node = node->children.nodes[i]; + for (size_t i = 0; i < node->children->size; i++) { + TreeNode *child_node = node->children->nodes[i]; bool _visited = false; - for (size_t j = 0; j < visited.size; j++) { - if (visited.nodes[j]->id == child_node->id) { + for (size_t j = 0; j < visited->size; j++) { + if (visited->nodes[j]->id == child_node->id) { _visited = true; break; } } if (!_visited) { - wm_nodearray_push(&visited, child_node); + wm_nodearray_push(visited, child_node); wm_ptrarray_push(&queue, child_node); } } } ret: - __wm_nodearray_free(&visited); + wm_nodearray_free(visited); wm_ptrarray_free(&queue); return ret; } @@ -849,10 +800,10 @@ TreeNode* wm_treenode_ptr_find_client_node(TreeNode *root, Client *client) assert(client); TreeNode *ret = NULL; - PtrArray client_nodes = wm_treenode_find_client_nodes_ptr(root); + NodeArray *client_nodes = wm_treenode_find_client_nodes(root); - for (size_t i = 0; i < client_nodes.size; i++) { - TreeNode *node = (TreeNode*)client_nodes.ptrs[i]; + for (size_t i = 0; i < client_nodes->size; i++) { + TreeNode *node = (TreeNode*)client_nodes->nodes[i]; if (node->client == client) { ret = node; goto ret; @@ -860,182 +811,69 @@ TreeNode* wm_treenode_ptr_find_client_node(TreeNode *root, Client *client) } ret: - wm_ptrarray_free(&client_nodes); + wm_nodearray_free(client_nodes); return ret; } -PtrArray wm_treenode_find_client_nodes_ptr(TreeNode *root) +NodeArray *wm_treenode_find_client_nodes(TreeNode *root) +{ + assert(root); + + NodeArray *ret = wm_nodearray_new(); + NodeArray *all_nodes = wm_all_nodes_to_array(root); + + for (size_t i = 0; i < all_nodes->size; i++) { + TreeNode *node = all_nodes->nodes[i]; + if (node->type == NODE_CLIENT && node->client) + wm_nodearray_push(ret, node); + } + + wm_nodearray_free(all_nodes); + return ret; +} + +NodeArray* wm_all_nodes_to_array(TreeNode *root) { DEBUG_PRINT("%s\n", __func__); assert(root); - PtrArray ret = wm_ptrarray_new(); + NodeArray *ret = wm_nodearray_new(); - NodeArray visited = wm_nodearray_new(); - wm_nodearray_push(&visited, root); + NodeArray *visited = wm_nodearray_new(); + wm_nodearray_push(visited, root); - PtrArray queue = wm_ptrarray_new(); + NodeArray *queue = wm_nodearray_new(); - wm_ptrarray_push(&queue, root); + wm_nodearray_push(queue, root); - while (queue.size > 0) { + while (queue->size > 0) { TreeNode *node; - if (!wm_ptrarray_pop_front(&queue, (void**)&node)) + if (!wm_nodearray_pop_front(queue, &node)) goto ret; - if (node->type == NODE_CLIENT && node->client != NULL) - wm_ptrarray_push(&ret, node); + wm_nodearray_push(ret, node); - for (size_t i = 0; i < node->children.size; i++) { - TreeNode *child_node = node->children.nodes[i]; + for (size_t i = 0; i < node->children->size; i++) { + TreeNode *child_node = node->children->nodes[i]; bool _visited = false; - for (size_t j = 0; j < visited.size; j++) { - if (visited.nodes[j]->id == child_node->id) { + for (size_t j = 0; j < visited->size; j++) { + if (visited->nodes[j]->id == child_node->id) { _visited = true; break; } } if (!_visited) { - wm_nodearray_push(&visited, child_node); - wm_ptrarray_push(&queue, child_node); + wm_nodearray_push(visited, child_node); + wm_nodearray_push(queue, child_node); } } } ret: - __wm_nodearray_free(&visited); - wm_ptrarray_free(&queue); + wm_nodearray_free(visited); + wm_nodearray_free(queue); return ret; } - -PtrArray wm_all_nodes_to_ptrarray(TreeNode *root) -{ - DEBUG_PRINT("%s\n", __func__); - assert(root); - - PtrArray ret = wm_ptrarray_new(); - - NodeArray visited = wm_nodearray_new(); - wm_nodearray_push(&visited, root); - - PtrArray queue = wm_ptrarray_new(); - - wm_ptrarray_push(&queue, root); - - while (queue.size > 0) { - TreeNode *node; - - if (!wm_ptrarray_pop_front(&queue, (void**)&node)) - goto ret; - - wm_ptrarray_push(&ret, node); - - for (size_t i = 0; i < node->children.size; i++) { - TreeNode *child_node = node->children.nodes[i]; - bool _visited = false; - - for (size_t j = 0; j < visited.size; j++) { - if (visited.nodes[j]->id == child_node->id) { - _visited = true; - break; - } - } - - if (!_visited) { - wm_nodearray_push(&visited, child_node); - wm_ptrarray_push(&queue, child_node); - } - } - } - -ret: - __wm_nodearray_free(&visited); - wm_ptrarray_free(&queue); - return ret; -} - -ClientArray wm_clientarray_new() -{ - ClientArray arr; - - arr.capacity = 10; - arr.clients = calloc(arr.capacity, sizeof(TreeNode)); - arr.size = 0; - - return arr; -} - -void wm_clientarray_push(ClientArray *arr, Client node) -{ - DEBUG_PRINT("%s\n", __func__); - assert(arr); - - arr->size++; - - if (arr->size >= arr->capacity) { - Client* temp = calloc(arr->capacity, sizeof(Client)); - memcpy(temp, arr->clients, arr->capacity * sizeof(Client)); - free(arr->clients); - size_t old_capacity = arr->capacity; - arr->capacity = old_capacity * 2; - - arr->clients = calloc(arr->capacity, sizeof(Client)); - memcpy(arr->clients, temp, old_capacity * sizeof(Client)); - - free(temp); - arr->clients[arr->size - 1] = node; - return; - } - - arr->clients[arr->size - 1] = node; -} - -bool wm_clientarray_pop(ClientArray *arr, Client *ret) -{ - DEBUG_PRINT("%s\n", __func__); - assert(arr); - - if (!ret || !arr) - return false; - - if (arr->size == 0) - return false; - - *ret = arr->clients[arr->size - 1]; - arr->size--; - return true; -} - -bool wm_clientarray_remove(ClientArray *arr, size_t index) -{ - DEBUG_PRINT("%s\n", __func__); - assert(arr); - - if (!arr) - return false; - - if (index >= arr->size) - return false; - - if (index == arr->size - 1) { - arr->size--; - return true; - } - - memmove(arr->clients + index, arr->clients + index+1, arr->size-1 * sizeof(Client)); - - return true; -} - -void wm_clientarray_free(ClientArray *arr) -{ - DEBUG_PRINT("%s\n", __func__); - assert(arr); - - arr->capacity = 0; - arr->size = 0; - free(arr->clients); -} diff --git a/src/util.h b/src/util.h index ec6b521..cc8651b 100644 --- a/src/util.h +++ b/src/util.h @@ -35,12 +35,6 @@ typedef struct { size_t capacity; } PtrArray; -typedef struct { - Client *clients; - size_t size; - size_t capacity; -} ClientArray; - typedef struct { int x; int y; @@ -53,7 +47,7 @@ struct TreeNode { TreeNode *parent; - NodeArray children; + NodeArray *children; Rect pos; @@ -66,6 +60,14 @@ typedef struct { char *str; } WmWorkspaceToStrRet; +NodeArray* wm_nodearray_new(); +void wm_nodearray_push(NodeArray *arr, TreeNode *node); +bool wm_nodearray_pop(NodeArray *arr, TreeNode **ret); +bool wm_nodearray_pop_front(NodeArray *arr, TreeNode **ret); +void wm_nodearray_clear(NodeArray *arr); +bool wm_nodearray_remove(NodeArray *arr, size_t index); +void wm_nodearray_free(NodeArray *arr); + TreeNode* wm_treenode_new(NodeType type, TreeNode *parent); void wm_treenode_free(TreeNode *node); bool wm_treenode_is_empty(TreeNode *node); @@ -80,15 +82,6 @@ void wm_node_type_to_str(NodeType type, char *buf, size_t bufsize); char* wm_treenode_to_str(TreeNode *node); void wm_treenode_print(TreeNode *node); -NodeArray wm_nodearray_new(); -void wm_nodearray_push(NodeArray *arr, TreeNode *node); -bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret); -bool wm_nodearray_pop_front(NodeArray *arr, TreeNode *ret); -void wm_nodearray_clear(NodeArray *arr); -bool wm_nodearray_remove(NodeArray *arr, size_t index); -void __wm_nodearray_free(NodeArray *arr); -ClientArray wm_nodearray_find_clients(TreeNode *root); - PtrArray wm_ptrarray_new(); void wm_ptrarray_push(PtrArray *arr, void* ptr); bool wm_ptrarray_pop(PtrArray *arr, void **ret); @@ -97,9 +90,9 @@ bool wm_ptrarray_remove(PtrArray *arr, size_t index); void wm_ptrarray_free(PtrArray *arr); TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root); TreeNode* wm_treenode_ptr_find_client_node(TreeNode *root, Client *client); -PtrArray wm_treenode_find_client_nodes_ptr(TreeNode *root); +NodeArray* wm_treenode_find_client_nodes(TreeNode *root); TreeNode* wm_treenode_split_get_sibling(TreeNode *node); -PtrArray wm_all_nodes_to_ptrarray(TreeNode *root); +NodeArray* wm_all_nodes_to_array(TreeNode *root); void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile); TreeNode* wm_treenode_lmd(TreeNode *node); @@ -108,10 +101,4 @@ PtrArray wm_postorder_traversal(TreeNode *tree); bool wm_is_treenode_keyroot(TreeNode *node); PtrArray wm_treenode_all_keyroots(TreeNode *node); -ClientArray wm_clientarray_new(); -void wm_clientarray_push(ClientArray *arr, Client node); -bool wm_clientarray_pop(ClientArray *arr, Client *ret); -bool wm_clientarray_remove(ClientArray *arr, size_t index); -void wm_clientarray_free(ClientArray *arr); - #endif diff --git a/src/wm.c b/src/wm.c index a0d000a..5f7ae55 100644 --- a/src/wm.c +++ b/src/wm.c @@ -218,8 +218,8 @@ void wm_ws_tree_insert_client(Wm *wm, Workspace *ws, Client *client) child2->client = client; focused_node->client = NULL; - wm_nodearray_push(&focused_node->children, child1); - wm_nodearray_push(&focused_node->children, child2); + wm_nodearray_push(focused_node->children, child1); + wm_nodearray_push(focused_node->children, child2); } void wm_switch_ws(Wm *wm, size_t ws) @@ -233,11 +233,10 @@ void wm_switch_ws(Wm *wm, size_t ws) DEBUG_PRINT("switching to ws %ld, clients:", ws); wm_treenode_print(wm->smon->workspaces[ws].tree); - PtrArray current_ws_clients = wm_treenode_find_client_nodes_ptr( - wm->smon->workspaces[wm->smon->selws].tree); + NodeArray *current_ws_clients = wm_treenode_find_client_nodes(CURRENT_WS(wm).tree); - for (size_t i = 0; i < current_ws_clients.size; i++) { - c = ((TreeNode**)current_ws_clients.ptrs)[i]->client; + for (size_t i = 0; i < current_ws_clients->size; i++) { + c = ((TreeNode**)current_ws_clients->nodes)[i]->client; assert(c); if (c->ws->index == wm->smon->selws) { DEBUG_PRINT("wm_switch_ws hide client selws: %ld\n", c->ws->index) @@ -250,11 +249,10 @@ void wm_switch_ws(Wm *wm, size_t ws) wm_client_set_atom(wm, &wm-> root, "_NET_CURRENT_DESKTOP", (unsigned char*) &(ws), XA_CARDINAL, 1); - PtrArray switch_ws_clients = wm_treenode_find_client_nodes_ptr( - wm->smon->workspaces[wm->smon->selws].tree); + NodeArray *switch_ws_clients = wm_treenode_find_client_nodes(CURRENT_WS(wm).tree); - for (size_t i = 0; i < switch_ws_clients.size; i++) { - c = ((TreeNode**)switch_ws_clients.ptrs)[i]->client; + for (size_t i = 0; i < switch_ws_clients->size; i++) { + c = ((TreeNode**)switch_ws_clients->nodes)[i]->client; if (c->ws->index == wm->smon->selws) { wscc++; wm_client_show(wm, c); @@ -268,8 +266,8 @@ void wm_switch_ws(Wm *wm, size_t ws) wm_layout(wm, wm->smon); - wm_ptrarray_free(¤t_ws_clients); - wm_ptrarray_free(&switch_ws_clients); + wm_nodearray_free(current_ws_clients); + wm_nodearray_free(switch_ws_clients); } void wm_move_client_ws(Wm *wm, int ws) @@ -303,12 +301,12 @@ void wm_layout(Wm *wm, Monitor *m) DEBUG_PRINT("%s\n", __func__); Workspace *ws = &m->workspaces[m->selws]; - PtrArray clients = wm_treenode_find_client_nodes_ptr(ws->tree); - if (clients.size == 0) + NodeArray *clients = wm_treenode_find_client_nodes(ws->tree); + if (clients->size == 0) goto ret; - for (i = 0; i < clients.size; i++) { - TreeNode *node = clients.ptrs[i]; + for (i = 0; i < clients->size; i++) { + TreeNode *node = clients->nodes[i]; Client *client = node->client; assert(client); @@ -323,7 +321,7 @@ void wm_layout(Wm *wm, Monitor *m) wm_client_show(wm, client); } - wm_client_focus(wm, ((TreeNode*)clients.ptrs[0])->client); + wm_client_focus(wm, ((TreeNode*)clients->nodes[0])->client); XEvent e; XSync(wm->display, False); @@ -332,7 +330,7 @@ void wm_layout(Wm *wm, Monitor *m) wm_monitor_clients_border(wm, m); ret: - wm_ptrarray_free(&clients); + wm_nodearray_free(clients); } Client *wm_get_last_client(Wm *wm, Monitor m) @@ -482,16 +480,16 @@ void wm_exit(Wm *wm) for (size_t i = 0; i < wm->wm_mc; i++) { for (size_t j = 0; j < wm->monitors[i].wscount; j++) { - PtrArray clients = wm_treenode_find_client_nodes_ptr( + NodeArray *clients = wm_treenode_find_client_nodes( wm->monitors[i].workspaces[j].tree); - for (size_t k = 0; k < clients.size; k++) { - Client *c = ((TreeNode*)clients.ptrs[k])->client; + for (size_t k = 0; k < clients->size; k++) { + Client *c = ((TreeNode*)clients->nodes[k])->client; XKillClient(wm->display, c->window); DEBUG_PRINT("freeing client %p\n", (void*)c); wm_client_free(wm, c); } - wm_ptrarray_free(&clients); + wm_nodearray_free(clients); } }