From b0f446a514aa003a95863a8412b4c4f39f1e2d08 Mon Sep 17 00:00:00 2001 From: Akos Horvath <koma@koma.sh> Date: Wed, 9 Aug 2023 19:59:05 +0200 Subject: [PATCH 1/4] make TreeNode struct heap-allocated --- src/util.c | 134 ++++++++++++++++++++++++++++------------------------- src/util.h | 9 ++-- 2 files changed, 75 insertions(+), 68 deletions(-) diff --git a/src/util.c b/src/util.c index 49a5548..ceb5a98 100644 --- a/src/util.c +++ b/src/util.c @@ -5,22 +5,29 @@ #include <string.h> #include <assert.h> -TreeNode wm_treenode_new(NodeType type, TreeNode *parent) +TreeNode* wm_treenode_new(NodeType type, TreeNode *parent) { DEBUG_PRINT("%s\n", __func__); - TreeNode node; + TreeNode *node = calloc(sizeof(TreeNode), 1); - node.parent = parent; - node.type = type; - node.children = wm_nodearray_new(); + node->parent = parent; + node->type = type; + node->children = wm_nodearray_new(); node_id++; - node.id = node_id; - node.client = NULL; + node->id = node_id; + node->client = NULL; return node; } +void wm_treenode_free(TreeNode *node) +{ + wm_nodearray_clear(&node->children); + __wm_nodearray_free(&node->children); + free(node); +} + bool wm_treenode_is_empty(TreeNode *node) { DEBUG_PRINT("%s\n", __func__); @@ -107,7 +114,7 @@ void wm_tree_to_DOT(TreeNode *root, const char *filename) bool contains = false; for (size_t j = 0; j < printed_nodes.size; j++) { - if (printed_nodes.nodes[i].id == node->id) + if (printed_nodes.nodes[j]->id == node->id) contains = true; } @@ -119,12 +126,12 @@ void wm_tree_to_DOT(TreeNode *root, const char *filename) 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, "}"); @@ -132,14 +139,14 @@ void wm_tree_to_DOT(TreeNode *root, const char *filename) fflush(fp); fclose(fp); - wm_nodearray_free(&printed_nodes); + __wm_nodearray_free(&printed_nodes); wm_ptrarray_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) + if (node_id == parent->children.nodes[i]->id) return i; } @@ -168,7 +175,7 @@ void wm_treenode_remove_node(TreeNode *root, unsigned int node_id) 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]; + TreeNode *sibling_node = node->parent->children.nodes[i]; if (sibling_node->id != node->id) { return sibling_node; } @@ -186,21 +193,20 @@ TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client) if (client_node->parent == NULL) { client_node->client = NULL; - wm_nodearray_clear(&client_node->children); - wm_nodearray_free(&client_node->children); + wm_treenode_free(client_node); return NULL; } 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) { + 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; - wm_nodearray_free(&client_node->children); - wm_nodearray_free(&node->children.nodes[i].children); + node->client = node->children.nodes[i]->client; + wm_treenode_free(client_node); + wm_treenode_free(node->children.nodes[i]); wm_nodearray_clear(&node->children); return node; } @@ -209,7 +215,7 @@ TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client) DEBUG_PRINT("%s: other_client was NULL!\n", __func__); TreeNode *sibling_node = wm_treenode_split_get_sibling(client_node); - wm_nodearray_free(&client_node->children); + wm_treenode_free(client_node); // wm_nodearray_free(&node->children); @@ -220,22 +226,22 @@ TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client) // parent is root node DEBUG_PRINT("parent is root node!\n"); sibling_node->parent = NULL; - client->ws->tree = *sibling_node; + client->ws->tree = sibling_node; - client->ws->tree.pos = (Rect) { + client->ws->tree->pos = (Rect) { .x = wm->config.border_width, .y = wm->config.border_width + dock_y , .w = client->ws->monitor->info.width - wm->config.border_width*2, .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 *node = *sibling_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() @@ -243,27 +249,27 @@ NodeArray wm_nodearray_new() NodeArray arr; arr.capacity = 10; - arr.nodes = calloc(arr.capacity, sizeof(TreeNode)); + arr.nodes = calloc(arr.capacity, sizeof(TreeNode*)); arr.size = 0; return arr; } -void wm_nodearray_push(NodeArray *arr, TreeNode node) +void wm_nodearray_push(NodeArray *arr, TreeNode *node) { assert(arr); arr->size++; if (arr->size >= arr->capacity) { - TreeNode* temp = calloc(arr->capacity, sizeof(TreeNode)); - memcpy(temp, arr->nodes, arr->capacity * sizeof(TreeNode)); + TreeNode* temp = calloc(arr->capacity, sizeof(TreeNode*)); + memcpy(temp, arr->nodes, arr->capacity * sizeof(TreeNode*)); free(arr->nodes); size_t old_capacity = arr->capacity; arr->capacity = old_capacity * 2; - arr->nodes = calloc(arr->capacity, sizeof(TreeNode)); - memcpy(arr->nodes, temp, old_capacity * sizeof(TreeNode)); + arr->nodes = calloc(arr->capacity, sizeof(TreeNode*)); + memcpy(arr->nodes, temp, old_capacity * sizeof(TreeNode*)); free(temp); arr->nodes[arr->size - 1] = node; @@ -282,7 +288,7 @@ 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; } @@ -295,9 +301,9 @@ 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)); + memmove(arr->nodes, arr->nodes+1, arr->size * sizeof(TreeNode*)); return true; } @@ -306,7 +312,7 @@ void wm_nodearray_clear(NodeArray *arr) { DEBUG_PRINT("%s\n", __func__); arr->size = 0; - memset(arr->nodes, 0, arr->capacity * sizeof(TreeNode)); + memset(arr->nodes, 0, arr->capacity * sizeof(TreeNode*)); } bool wm_nodearray_remove(NodeArray *arr, size_t index) @@ -325,14 +331,14 @@ bool wm_nodearray_remove(NodeArray *arr, size_t index) return true; } - memmove(arr->nodes + index, arr->nodes + index+1, arr->size-1 * sizeof(TreeNode)); + memmove(arr->nodes + index, arr->nodes + index+1, arr->size-1 * sizeof(TreeNode*)); return true; } -void wm_nodearray_free(NodeArray *arr) +void __wm_nodearray_free(NodeArray *arr) { - DEBUG_PRINT("%s\n", __func__); + // DEBUG_PRINT("%s\n", __func__); assert(arr); arr->capacity = 0; @@ -349,12 +355,12 @@ ClientArray wm_nodearray_find_clients(TreeNode *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); + wm_nodearray_push(&visited, root); NodeArray queue = wm_nodearray_new(); ClientArray clients = wm_clientarray_new(); - wm_nodearray_push(&queue, *root); + wm_nodearray_push(&queue, root); while (queue.size > 0) { TreeNode node; @@ -366,11 +372,11 @@ ClientArray wm_nodearray_find_clients(TreeNode *root) wm_clientarray_push(&clients, *node.client); for (size_t i = 0; i < node.children.size; i++) { - TreeNode child_node = node.children.nodes[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) { + if (visited.nodes[j]->id == child_node->id) { _visited = true; break; } @@ -384,8 +390,8 @@ ClientArray wm_nodearray_find_clients(TreeNode *root) } ret: - wm_nodearray_free(&visited); - wm_nodearray_free(&queue); + __wm_nodearray_free(&visited); + __wm_nodearray_free(&queue); return clients; } @@ -476,7 +482,7 @@ bool wm_ptrarray_remove(PtrArray *arr, size_t index) void wm_ptrarray_free(PtrArray *arr) { - DEBUG_PRINT("%s\n", __func__); + // DEBUG_PRINT("%s\n", __func__); assert(arr); arr->capacity = 0; @@ -492,7 +498,7 @@ TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root) TreeNode *ret = NULL; NodeArray visited = wm_nodearray_new(); - wm_nodearray_push(&visited, *root); + wm_nodearray_push(&visited, root); PtrArray queue = wm_ptrarray_new(); @@ -510,25 +516,25 @@ TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root) } for (size_t i = 0; i < node->children.size; i++) { - TreeNode *child_node = &node->children.nodes[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) { + 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; } @@ -562,7 +568,7 @@ PtrArray wm_treenode_find_client_nodes_ptr(TreeNode *root) PtrArray ret = wm_ptrarray_new(); NodeArray visited = wm_nodearray_new(); - wm_nodearray_push(&visited, *root); + wm_nodearray_push(&visited, root); PtrArray queue = wm_ptrarray_new(); @@ -578,25 +584,25 @@ PtrArray wm_treenode_find_client_nodes_ptr(TreeNode *root) wm_ptrarray_push(&ret, node); for (size_t i = 0; i < node->children.size; i++) { - TreeNode *child_node = &node->children.nodes[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) { + 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; } @@ -609,7 +615,7 @@ PtrArray wm_all_nodes_to_ptrarray(TreeNode *root) PtrArray ret = wm_ptrarray_new(); NodeArray visited = wm_nodearray_new(); - wm_nodearray_push(&visited, *root); + wm_nodearray_push(&visited, root); PtrArray queue = wm_ptrarray_new(); @@ -624,25 +630,25 @@ PtrArray wm_all_nodes_to_ptrarray(TreeNode *root) wm_ptrarray_push(&ret, node); for (size_t i = 0; i < node->children.size; i++) { - TreeNode *child_node = &node->children.nodes[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) { + 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; } diff --git a/src/util.h b/src/util.h index fbf244c..5268d51 100644 --- a/src/util.h +++ b/src/util.h @@ -25,7 +25,7 @@ typedef enum NodeType { typedef struct TreeNode TreeNode; typedef struct { - TreeNode *nodes; + TreeNode **nodes; size_t size; size_t capacity; } NodeArray; @@ -62,7 +62,8 @@ struct TreeNode { unsigned int id; }; -TreeNode wm_treenode_new(NodeType type, TreeNode *parent); +TreeNode* wm_treenode_new(NodeType type, TreeNode *parent); +void wm_treenode_free(TreeNode *node); bool wm_treenode_is_empty(TreeNode *node); void wm_treenode_split_space(TreeNode *node, Rect *ret1, Rect *ret2); TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client); @@ -72,12 +73,12 @@ void wm_tree_to_DOT(TreeNode *root, const char *filename); void wm_node_type_to_str(NodeType type, char *buf, size_t bufsize); NodeArray wm_nodearray_new(); -void wm_nodearray_push(NodeArray *arr, TreeNode node); +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); +void __wm_nodearray_free(NodeArray *arr); ClientArray wm_nodearray_find_clients(TreeNode *root); From 077c2b5f69e9f12678918d1336270ce85c93964f Mon Sep 17 00:00:00 2001 From: Akos Horvath <koma@koma.sh> Date: Wed, 9 Aug 2023 20:00:06 +0200 Subject: [PATCH 2/4] update TreeNode function usages to use pointers --- src/client.c | 23 ++++++++--------------- src/wm.c | 42 +++++++++++++++++++----------------------- src/wm.h | 2 +- 3 files changed, 28 insertions(+), 39 deletions(-) diff --git a/src/client.c b/src/client.c index ac30709..42016cc 100644 --- a/src/client.c +++ b/src/client.c @@ -40,7 +40,7 @@ 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); + PtrArray clients = wm_treenode_find_client_nodes_ptr(wm->smon->workspaces[wm->smon->selws].tree); Client *ret = NULL; for (size_t i = 0; i < clients.size; i++) { @@ -83,15 +83,6 @@ Client* wm_client_create(Wm *wm, Window w) strcpy(c->name, (char*)xtp.value); } - if (wm->smon->clients == NULL) { - wm->smon->clients = c; - } else { - t = wm_get_last_client(wm, *c->m); - t->next = c; - c->prev = t; - c->next = NULL; - } - XSelectInput(wm->display, c->window, FocusChangeMask | EnterWindowMask | PointerMotionMask); @@ -131,6 +122,7 @@ void wm_client_handle_window_types(Wm *wm, Client *c, XMapRequestEvent e) } else if (strcmp(atom_name, "_NET_WM_WINDOW_TYPE_DIALOG") == 0) { c->is_floating = true; } + XFree(atom_name); } if (!is_normal) { @@ -239,7 +231,7 @@ void wm_client_kill(Wm *wm, Client *c) if (XSendEvent(wm->display, c->window, false, NoEventMask, &event) != Success) XKillClient(wm->display, c->window); - TreeNode* parent = wm_treenode_remove_client(wm, &c->ws->tree, c); + TreeNode* parent = wm_treenode_remove_client(wm, c->ws->tree, c); wm_client_free(wm, c); wm->focused_client = NULL; @@ -310,7 +302,7 @@ Client* wm_client_get_dir_rel_c(Client *c, int dir) if (!c) return NULL; - Client *r; + Client *r = NULL; int x, y, dx, dy; switch (dir) { @@ -343,7 +335,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); + PtrArray client_nodes = wm_treenode_find_client_nodes_ptr(c->ws->tree); x+=dx*5; y+=dy*5; @@ -364,6 +356,7 @@ Client* wm_client_get_dir_rel_c(Client *c, int dir) } while((x > 0 && x < c->m->info.width) && (y > 0 && y < c->m->info.height)); + DEBUG_PRINT("%s returning %p\n", __func__, r); return r; } @@ -372,7 +365,7 @@ Client* wm_client_get_focused(Wm *wm) Client *c = NULL; Workspace *ws = &wm->smon->workspaces[wm->smon->selws]; - TreeNode *node = wm_treenode_ptr_find_focused_client_node(&ws->tree); + TreeNode *node = wm_treenode_ptr_find_focused_client_node(ws->tree); if (!node) return NULL; @@ -412,7 +405,7 @@ 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); + PtrArray clients = wm_treenode_find_client_nodes_ptr(m->workspaces[m->selws].tree); if (clients.size == 0) return; diff --git a/src/wm.c b/src/wm.c index 0229fdd..41c7727 100644 --- a/src/wm.c +++ b/src/wm.c @@ -192,10 +192,10 @@ void wm_ws_tree_insert_client(Wm *wm, Workspace *ws, Client *client) dock_y = x.height; } - if (wm_treenode_is_empty(&ws->tree) && ws->tree.client == NULL) { - ws->tree.type = NODE_CLIENT; - ws->tree.client = client; - ws->tree.pos = (Rect) { + if (wm_treenode_is_empty(ws->tree) && ws->tree->client == NULL) { + ws->tree->type = NODE_CLIENT; + ws->tree->client = client; + ws->tree->pos = (Rect) { .x = wm->config.border_width, .y = wm->config.border_width + dock_y , .w = ws->monitor->info.width - wm->config.border_width*2, .h = ws->monitor->info.height - wm->config.border_width*2 - dock_y, @@ -203,18 +203,18 @@ void wm_ws_tree_insert_client(Wm *wm, Workspace *ws, Client *client) return; } - TreeNode *focused_node = wm_treenode_ptr_find_focused_client_node(&ws->tree); + TreeNode *focused_node = wm_treenode_ptr_find_focused_client_node(ws->tree); assert(focused_node); Client *old_client = focused_node->client; focused_node->type = wm_split_to_nodetype(ws->split); - TreeNode child1 = wm_treenode_new(NODE_CLIENT, focused_node); - TreeNode child2 = wm_treenode_new(NODE_CLIENT, focused_node); + TreeNode *child1 = wm_treenode_new(NODE_CLIENT, focused_node); + TreeNode *child2 = wm_treenode_new(NODE_CLIENT, focused_node); - wm_treenode_split_space(focused_node, &child1.pos, &child2.pos); - child1.client = old_client; - child2.client = client; + wm_treenode_split_space(focused_node, &child1->pos, &child2->pos); + child1->client = old_client; + child2->client = client; wm_nodearray_push(&focused_node->children, child1); wm_nodearray_push(&focused_node->children, child2); @@ -229,7 +229,7 @@ void wm_switch_ws(Wm *wm, size_t ws) Client *c; PtrArray current_ws_clients = wm_treenode_find_client_nodes_ptr( - &wm->smon->workspaces[wm->smon->selws].tree); + wm->smon->workspaces[wm->smon->selws].tree); for (size_t i = 0; i < current_ws_clients.size; i++) { c = ((TreeNode**)current_ws_clients.ptrs)[i]->client; @@ -246,7 +246,7 @@ void wm_switch_ws(Wm *wm, size_t ws) (unsigned char*) &(ws), XA_CARDINAL, 1); PtrArray switch_ws_clients = wm_treenode_find_client_nodes_ptr( - &wm->smon->workspaces[wm->smon->selws].tree); + wm->smon->workspaces[wm->smon->selws].tree); for (size_t i = 0; i < switch_ws_clients.size; i++) { c = ((TreeNode**)switch_ws_clients.ptrs)[i]->client; @@ -377,7 +377,7 @@ 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); + PtrArray clients = wm_treenode_find_client_nodes_ptr(ws->tree); if (clients.size == 0) goto ret; @@ -411,6 +411,7 @@ ret: Client *wm_get_last_client(Wm *wm, Monitor m) { + return NULL; Client *c = m.clients; if (c == NULL) @@ -549,7 +550,6 @@ void wm_exit(Wm *wm) DEBUG_PRINT("%s\n", __func__); XUngrabKey(wm->display, AnyKey, AnyModifier, wm->root.window); - PtrArray all_clients = wm_ptrarray_new(); // TODO: perhaps add created clients to a PtrArray field in workspace. // would reduce number of calls to wm_treenode_find_client_nodes_ptr @@ -557,24 +557,20 @@ 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( - &wm->monitors[i].workspaces[j].tree); + wm->monitors[i].workspaces[j].tree); for (size_t k = 0; k < clients.size; k++) { - wm_ptrarray_push(&all_clients, clients.ptrs[i]); + Client *c = ((TreeNode*)clients.ptrs[k])->client; + XKillClient(wm->display, c->window); + DEBUG_PRINT("freeing client %p\n", c); + wm_client_free(wm, c); } wm_ptrarray_free(&clients); } } - for (size_t i = 0; i < all_clients.size; i++) { - Client *c = ((TreeNode*)all_clients.ptrs[i])->client; - XKillClient(wm->display, c->window); - wm_client_free(wm, c); - } - XCloseDisplay(wm->display); - wm_ptrarray_free(&all_clients); exit(EXIT_SUCCESS); } diff --git a/src/wm.h b/src/wm.h index b8dc6f8..c08f810 100644 --- a/src/wm.h +++ b/src/wm.h @@ -90,7 +90,7 @@ struct Monitor { }; struct Workspace { - TreeNode tree; + TreeNode *tree; size_t index; char name[WM_WS_NAME_LEN]; Monitor *monitor; From ce2fb27ccbc9f6807113427d347e39ec3cc39f94 Mon Sep 17 00:00:00 2001 From: Akos Horvath <koma@koma.sh> Date: Thu, 10 Aug 2023 12:01:38 +0200 Subject: [PATCH 3/4] fix XGetWMName leak --- src/client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client.c b/src/client.c index 42016cc..1a517f2 100644 --- a/src/client.c +++ b/src/client.c @@ -88,6 +88,8 @@ Client* wm_client_create(Wm *wm, Window w) wm_client_set_atom(wm, c, "_NET_WM_DESKTOP", (unsigned char*)&c->ws, XA_CARDINAL, 1); + + XFree(xtp.value); return c; } From 57cfbe44969c51d607fc85bcf1af1704d8d87665 Mon Sep 17 00:00:00 2001 From: Akos Horvath <koma@koma.sh> Date: Thu, 10 Aug 2023 12:02:43 +0200 Subject: [PATCH 4/4] fix client removal edge case --- src/util.c | 21 ++++++++++++++++++++- src/util.h | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/util.c b/src/util.c index ceb5a98..af2dfc9 100644 --- a/src/util.c +++ b/src/util.c @@ -73,6 +73,16 @@ void wm_treenode_split_space(TreeNode *node, Rect *ret1, Rect *ret2) } } +void wm_treenode_recalculate_space(TreeNode *node) +{ + assert(node); + + assert(node->children.size == 2); + + wm_treenode_split_space(node, &node->children.nodes[0]->pos, + &node->children.nodes[1]->pos); +} + void wm_node_type_to_str(NodeType type, char *buf, size_t bufsize) { switch (type) { @@ -237,9 +247,18 @@ TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client) 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 + } 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; + } + + wm_treenode_recalculate_space(node->parent); + wm_treenode_recalculate_space(node); + } + assert(client->ws->tree->children.size >= 1); return node->children.nodes[0]; } diff --git a/src/util.h b/src/util.h index 5268d51..890e12e 100644 --- a/src/util.h +++ b/src/util.h @@ -66,6 +66,7 @@ TreeNode* wm_treenode_new(NodeType type, TreeNode *parent); void wm_treenode_free(TreeNode *node); bool wm_treenode_is_empty(TreeNode *node); void wm_treenode_split_space(TreeNode *node, Rect *ret1, Rect *ret2); +void wm_treenode_recalculate_space(TreeNode *node); TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client); void wm_treenode_remove_node(TreeNode *root, unsigned int node_id); int wm_get_node_index(TreeNode *parent, unsigned int node_id);