From 2a8fdab5ce88fea5baf002488982c1bc27b35f03 Mon Sep 17 00:00:00 2001 From: Akos Horvath Date: Fri, 12 Apr 2024 11:51:58 +0200 Subject: [PATCH] add tab layout implementation --- src/client.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/handler.c | 5 ++- src/util.h | 17 ++++++++++ 3 files changed, 109 insertions(+), 4 deletions(-) diff --git a/src/client.c b/src/client.c index 42bb17f..080cb3a 100644 --- a/src/client.c +++ b/src/client.c @@ -20,6 +20,7 @@ along with this program. If not, see . #include "client.h" #include "util.h" #include "wm.h" +#include #include #include #include @@ -158,6 +159,7 @@ void wm_client_handle_window_types(Wm *wm, Client *c, XMapRequestEvent e) void wm_client_hide(Wm *wm, Client *c) { RETURN_IF_NULL(c); + DEBUG_PRINT("%s\n", __func__); if (c->hidden) return; @@ -165,11 +167,13 @@ void wm_client_hide(Wm *wm, Client *c) c->hidden = true; XUnmapWindow(wm->display, c->frame); XUnmapWindow(wm->display, c->window); + XSync(wm->display, False); } void wm_client_show(Wm *wm, Client *c) { RETURN_IF_NULL(c); + DEBUG_PRINT("%s\n", __func__); if (!c->hidden) return; @@ -177,6 +181,7 @@ void wm_client_show(Wm *wm, Client *c) c->hidden = false; XMapWindow(wm->display, c->frame); XMapWindow(wm->display, c->window); + XSync(wm->display, False); } void wm_client_focus(Wm *wm, Client *c) @@ -190,13 +195,35 @@ void wm_client_focus(Wm *wm, Client *c) if (old_focused_client) old_focused_client->focused = false; + XWindowAttributes att; + XGetWindowAttributes(wm->display, c->window, &att); + if (att.map_state == IsUnmapped) + XMapWindow(wm->display, c->window); + + XGetWindowAttributes(wm->display, c->frame, &att); + if (att.map_state == IsUnmapped) + XMapWindow(wm->display, c->frame); + + c->hidden = false; + XSetInputFocus(wm->display, c->window, RevertToPointerRoot, CurrentTime); wm_client_set_atom(wm, c, "_NET_ACTIVE_WINDOW", (unsigned char*) &c->window, XA_WINDOW, 1); + XSync(wm->display, False); + + TreeNode *node = wm_treenode_ptr_find_client_node(c->ws->tree, c); + if (node && node->parent && node->parent->type == NODE_TAB) { + for (size_t i = 0; i < node->parent->children->size; i++) { + node->parent->children->nodes[i]->client->focused = false; + } + } + c->focused = true; wm->focused_client = c; - TreeNode *node = wm_treenode_ptr_find_client_node(c->ws->tree, c); c->ws->focused_node = node; + if (node && node->parent && node->parent->type == NODE_TAB) { + wm_layout(wm, c->ws->monitor); + } wm_monitor_clients_border(wm, c->m); wm_monitor_draw_all_clients_frame(wm, c->m); } @@ -342,6 +369,37 @@ Client* wm_find_client_direction(Client *c, int dir) if (!c) return NULL; + TreeNode *node = wm_treenode_ptr_find_client_node(c->ws->tree, c); + + if (node->parent && node->parent->type == NODE_TAB) { + TreeNode *parent = node->parent; + int client_index = INT_MAX; + + for (int i = 0; i < parent->children->size; i++) { + if (parent->children->nodes[i]->client == c) { + client_index = i; + break; + } + } + + assert(client_index != INT_MAX); + + switch (dir) { + case LEFT: + if (client_index - 1 < 0) + return parent->children->nodes[parent->children->size-1]->client; + else + return parent->children->nodes[client_index - 1]->client; + break; + case RIGHT: + if (client_index + 1 >= parent->children->size) + return parent->children->nodes[0]->client; + else + return parent->children->nodes[client_index + 1]->client; + break; + } + } + Client *ret = NULL; int x, y, dx, dy; @@ -416,6 +474,7 @@ Client* wm_client_get_focused(Wm *wm) void wm_client_border(Wm *wm, Client *c) { + if (wm->config.show_titlebar) return; RETURN_IF_NULL(c); XVisualInfo vinfo; @@ -444,6 +503,7 @@ void wm_client_border(Wm *wm, Client *c) void wm_monitor_clients_border(Wm *wm, Monitor *m) { + if (wm->config.show_titlebar) return; DEBUG_PRINT("%s\n", __func__) RETURN_IF_NULL(m); NodeArray *clients = wm_treenode_find_client_nodes(m->workspaces[m->selected_ws].tree); @@ -482,6 +542,10 @@ void wm_client_draw_frame(Wm *wm, Client *c) if (!wm->config.show_titlebar) return; DEBUG_PRINT("%s\n", __func__); + TreeNode *node = wm_treenode_ptr_find_client_node(CURRENT_WS(wm).tree, c); + if (node->parent && node->parent->type == NODE_TAB) { + return; + } int screen = DefaultScreen(wm->display); Visual *visual = DefaultVisual(wm->display, screen); @@ -504,6 +568,31 @@ void wm_monitor_draw_all_clients_frame(Wm* wm, Monitor *m) if (clients->size == 0) return; + NodeArray *nodes = wm_all_nodes_to_array(m->workspaces[m->selected_ws].tree); + for (size_t i = 0; i < nodes->size; i++) { + TreeNode *node = nodes->nodes[i]; + if (node->type != NODE_TAB) continue; + + int screen = DefaultScreen(wm->display); + Visual *visual = DefaultVisual(wm->display, screen); + Colormap cmap = DefaultColormap(wm->display, screen); + + for (size_t j = 0; j < node->children->size; j++) { + Client *client = node->children->nodes[j]->client; + if (client->ws->index != m->selected_ws) continue; + + XftDraw *draw = XftDrawCreate(wm->display, node->tab_frame, visual, cmap); + + XftDrawRect(draw, (wm_client_is_focused(wm, client) ? &wm->titlebar_focused_color : + &wm->titlebar_color), j * client->w / node->children->size, 0, client->w, client->h); + + XftDrawStringUtf8(draw, &wm->titlebar_text_color, wm->titlebar_font, + 20 + j * client->w / node->children->size, 30, (void*)client->name, strlen(client->name)); + XftDrawDestroy(draw); + } + } + wm_nodearray_free(nodes); + for (size_t i = 0; i < clients->size; i++) { Client *client = ((TreeNode*)clients->nodes[i])->client; wm_client_draw_frame(wm, client); diff --git a/src/handler.c b/src/handler.c index 47490c9..16f8319 100644 --- a/src/handler.c +++ b/src/handler.c @@ -104,13 +104,12 @@ void wm_maprequest_handler(Wm *wm, XMapRequestEvent e) XSetWMName(wm->display, frame, &xtp); XFree(xtp.value); - XMapWindow(wm->display, frame); - XMapWindow(wm->display, e.window); - c = wm_client_create(wm, e.window); RETURN_IF_NULL(c); c->frame = frame; + wm_client_show(wm, c); + wm_ws_tree_insert_client(wm, c->ws, c); wm_client_handle_window_types(wm, c, e); diff --git a/src/util.h b/src/util.h index 55c2a90..8b91fbf 100644 --- a/src/util.h +++ b/src/util.h @@ -1,6 +1,7 @@ #ifndef UTIL_H #define UTIL_H +#include #include #include #include @@ -55,6 +56,8 @@ struct TreeNode { Client *client; unsigned int id; uint64_t distance; + + Window tab_frame; }; typedef struct { @@ -113,6 +116,11 @@ void wm_nodearray_clear(NodeArray *arr); */ bool wm_nodearray_remove(NodeArray *arr, size_t index); +/** + * Returns true if `arr` contains `node`. + */ +bool wm_nodearray_contains(NodeArray *arr, TreeNode *node); + /** * Frees the array. */ @@ -276,6 +284,12 @@ TreeNode* wm_treenode_ptr_find_client_node(TreeNode *root, Client *client); */ NodeArray* wm_treenode_find_client_nodes(TreeNode *root); +/** + * Searches for `child` in `parent->children`, and returns the index of `child`. + * If child could not be found, returns `SIZE_MAX`. + */ +size_t wm_treenode_find_index(TreeNode *parent, TreeNode* child); + /** * Returns the sibling node of `node`. * Returns NULL on error. @@ -372,6 +386,9 @@ void wm_logentries_free(UIntArray *entries); * array with the parsed values. * Return type: UIntArray */ +LogEntry *wm_json_obj_to_logentry(const char *key, struct json_object *jobj); + +/* UIntArray */ UIntArray* wm_read_log(const char* filename); /**