From 0006a90c862e9c010c74ca339809ac0103336d15 Mon Sep 17 00:00:00 2001 From: Akos Horvath Date: Sun, 31 Mar 2024 20:05:33 +0200 Subject: [PATCH] add reparenting and titlebars --- src/client.c | 41 +++++++++++++++++++++++++++++++++ src/client.h | 4 +++- src/config.c | 30 ++++++++++++++++++++++-- src/config.h | 5 ++++ src/handler.c | 14 +++++++++++ src/wm.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++---- src/wm.h | 6 +++++ 7 files changed, 157 insertions(+), 7 deletions(-) diff --git a/src/client.c b/src/client.c index 5611c92..ad7f867 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 @@ -162,6 +163,7 @@ void wm_client_hide(Wm *wm, Client *c) return; c->hidden = true; + XUnmapWindow(wm->display, c->frame); XUnmapWindow(wm->display, c->window); } @@ -173,6 +175,7 @@ void wm_client_show(Wm *wm, Client *c) return; c->hidden = false; + XMapWindow(wm->display, c->frame); XMapWindow(wm->display, c->window); } @@ -195,6 +198,7 @@ void wm_client_focus(Wm *wm, Client *c) TreeNode *node = wm_treenode_ptr_find_client_node(c->ws->tree, c); c->ws->focused_node = node; wm_monitor_clients_border(wm, c->m); + wm_monitor_draw_all_clients_frame(wm, c->m); } void wm_client_focus_dir(Wm *wm, Client *c, int dir) @@ -270,6 +274,8 @@ void wm_client_kill(Wm *wm, Client *c) if (XSendEvent(wm->display, c->window, false, NoEventMask, &event) != Success) XKillClient(wm->display, c->window); + XDestroyWindow(wm->display, c->frame); + TreeNode* parent = wm_treenode_remove_client(wm, c->ws->tree, c); wm_client_free(wm, c); @@ -470,3 +476,38 @@ bool wm_client_is_focused(Wm *wm, Client *c) return false; } + +void wm_client_draw_frame(Wm *wm, Client *c) +{ + if (!wm->config.show_titlebar) return; + DEBUG_PRINT("%s\n", __func__); + + + int screen = DefaultScreen(wm->display); + Visual *visual = DefaultVisual(wm->display, screen); + Colormap cmap = DefaultColormap(wm->display, screen); + + XftDraw *draw = XftDrawCreate(wm->display, c->frame, visual, cmap); + + XftDrawRect(draw, (wm_client_is_focused(wm, c) ? &wm->titlebar_focused_color : + &wm->titlebar_color), 0, 0, c->w, c->h); + + XftDrawStringUtf8(draw, &wm->titlebar_text_color, wm->titlebar_font, + 20, 30, (void*)c->name, strlen(c->name)); + XftDrawDestroy(draw); +} + +void wm_monitor_draw_all_clients_frame(Wm* wm, Monitor *m) +{ + DEBUG_PRINT("%s\n", __func__); + NodeArray *clients = wm_treenode_find_client_nodes(m->workspaces[m->selected_ws].tree); + if (clients->size == 0) + return; + + for (size_t i = 0; i < clients->size; i++) { + Client *client = ((TreeNode*)clients->nodes[i])->client; + wm_client_draw_frame(wm, client); + } + + wm_nodearray_free(clients); +} diff --git a/src/client.h b/src/client.h index c11da49..6ecad1a 100644 --- a/src/client.h +++ b/src/client.h @@ -38,6 +38,7 @@ struct Client { bool hidden; Monitor *m; Window window; + Window frame; Client *prev; Client *next; char *name; @@ -72,6 +73,7 @@ void wm_client_border_focused(Wm* wm, Client *c); void wm_monitor_clients_border(Wm* wm, Monitor *m); bool wm_client_is_focused(Wm* wm, Client *c); - +void wm_client_draw_frame(Wm *wm, Client *c); +void wm_monitor_draw_all_clients_frame(Wm* wm, Monitor *m); #endif diff --git a/src/config.c b/src/config.c index 05a8992..0a4dc8f 100644 --- a/src/config.c +++ b/src/config.c @@ -57,10 +57,15 @@ static const KeybindFunctionCommand __wm_keybind_commands[] = { void wm_cfg_init_def(Config *config) { config->ms_p = 0.5; - strncpy(config->border_col, "#222222", CONFIG_COLOR_MAX); - strncpy(config->focused_border_col, "#444444", CONFIG_COLOR_MAX); + strcpy(config->border_col, "#222222"); + strcpy(config->focused_border_col, "#444444"); config->border_width = 2; config->focus_on_motion = true; + config->show_titlebar = true; + strcpy(config->titlebar_color, "#000000"); + strcpy(config->titlebar_focused_color, "#4169e1"); + strcpy(config->titlebar_font, "monospace:size=18:antialias=true"); + strcpy(config->titlebar_text_color, "#ffffff"); wm_keybinds_init_def(config); @@ -237,6 +242,26 @@ void wm_configfile_init(ConfigFile *config, const char *filename) (ConfigCommand) {.string = "focus_on_motion", .arg_count = 1, .cfg_var_offset[0] = offsetof(Config, focus_on_motion), .argc = 0, .arg_type = TYPE_BOOL}, + + (ConfigCommand) {.string = "show_titlebar", .arg_count = 1, + .cfg_var_offset[0] = offsetof(Config, show_titlebar), + .argc = 0, .arg_type = TYPE_BOOL}, + + (ConfigCommand) {.string = "titlebar_color", .arg_count = 1, + .cfg_var_offset[0] = offsetof(Config, titlebar_color), + .argc = 0, .arg_type = TYPE_STRING}, + + (ConfigCommand) {.string = "titlebar_focused_color", .arg_count = 1, + .cfg_var_offset[0] = offsetof(Config, titlebar_focused_color), + .argc = 0, .arg_type = TYPE_STRING}, + + (ConfigCommand) {.string = "titlebar_font", .arg_count = 1, + .cfg_var_offset[0] = offsetof(Config, titlebar_font), + .argc = 0, .arg_type = TYPE_STRING}, + + (ConfigCommand) {.string = "titlebar_text_color", .arg_count = 1, + .cfg_var_offset[0] = offsetof(Config, titlebar_text_color), + .argc = 0, .arg_type = TYPE_STRING}, }; config->command_count = sizeof(commands) / sizeof (commands[0]); @@ -605,6 +630,7 @@ int wm_string_to_direction(const char *str) KeybindFunction wm_str_to_keybindfunction(const char* str) { DEBUG_PRINT("%s %s\n", __func__, str); + char lower[CONFIG_ARGLEN_MAX]; strncpy(lower, str, CONFIG_ARGLEN_MAX); diff --git a/src/config.h b/src/config.h index f568587..04ce792 100644 --- a/src/config.h +++ b/src/config.h @@ -87,6 +87,11 @@ typedef struct { Keybind *keybinds; int kb_count; bool focus_on_motion; + bool show_titlebar; + char titlebar_color[CONFIG_COLOR_MAX]; + char titlebar_focused_color[CONFIG_COLOR_MAX]; + char titlebar_font[CONFIG_ARGLEN_MAX]; + char titlebar_text_color[CONFIG_COLOR_MAX]; char log_path[PATH_MAX]; } Config; diff --git a/src/handler.c b/src/handler.c index aaea23c..47490c9 100644 --- a/src/handler.c +++ b/src/handler.c @@ -94,8 +94,22 @@ void wm_maprequest_handler(Wm *wm, XMapRequestEvent e) DEBUG_PRINT("%s: client not found, creating client\n", __func__) + Window frame = XCreateSimpleWindow(wm->display, wm->root.window, 0, 0, + 10, 10, 0, 0, 0); + + XReparentWindow(wm->display, e.window, frame, 0, 0); + + XTextProperty xtp; + XGetWMName(wm->display, e.window, &xtp); + 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_ws_tree_insert_client(wm, c->ws, c); diff --git a/src/wm.c b/src/wm.c index 6776989..5b5535b 100644 --- a/src/wm.c +++ b/src/wm.c @@ -31,6 +31,7 @@ along with this program. If not, see . #include #include #include +#include #include "wm.h" #include "config.h" #include "handler.h" @@ -317,11 +318,21 @@ void wm_layout(Wm *wm, Monitor *m) unsigned int value_mask = CWX | CWY | CWWidth | CWHeight; XWindowChanges xwc = wm_client_to_xwchanges((client)); - XConfigureWindow(wm->display, client->window, value_mask, &xwc); - wm_client_show(wm, client); - } + XConfigureWindow(wm->display, client->frame, value_mask, &xwc); - wm_client_focus(wm, ((TreeNode*)clients->nodes[0])->client); + if (wm->config.show_titlebar) { + xwc.y = wm->titlebar_font->height * 2; + xwc.x = 0; + xwc.height -= wm->titlebar_font->height * 2; + } else { + xwc.y = 0; + xwc.x = 0; + } + + XConfigureWindow(wm->display, client->window, value_mask, &xwc); + + wm_client_draw_frame(wm, client); + } XEvent e; XSync(wm->display, False); @@ -444,6 +455,42 @@ void wm_init(Wm *wm) // exit(1); // } + // initialize titlebar font + int screen = DefaultScreen(wm->display); + wm->titlebar_font = XftFontOpenName(wm->display, screen, wm->config.titlebar_font); + if (!wm->titlebar_font) { + fprintf(stderr, "wm: could not open font \"%s\". exiting.\n", + wm->config.titlebar_font); + exit(1); + } + + // initialize titlebar colors + Visual *visual = DefaultVisual(wm->display, screen); + Colormap cmap = DefaultColormap(wm->display, screen); + int ret = XftColorAllocName(wm->display, visual, cmap, wm->config.titlebar_color, + &wm->titlebar_color); + if (ret == 0) { + fprintf(stderr, "wm: could not allocate color \"%s\". exiting.\n", + wm->config.titlebar_color); + exit(1); + } + + ret = XftColorAllocName(wm->display, visual, cmap, wm->config.titlebar_focused_color, + &wm->titlebar_focused_color); + if (ret == 0) { + fprintf(stderr, "wm: could not allocate color \"%s\". exiting.\n", + wm->config.titlebar_focused_color); + exit(1); + } + + ret = XftColorAllocName(wm->display, visual, cmap, wm->config.titlebar_text_color, + &wm->titlebar_text_color); + if (ret == 0) { + fprintf(stderr, "wm: could not allocate color \"%s\". exiting.\n", + wm->config.titlebar_text_color); + exit(1); + } + wm_set_supported_atoms(wm); wm->dock = ULONG_MAX; @@ -479,6 +526,15 @@ void wm_exit(Wm *wm) } } + // free titlebar font and colors + int screen = DefaultScreen(wm->display); + Visual *visual = DefaultVisual(wm->display, screen); + Colormap cmap = DefaultColormap(wm->display, screen); + XftColorFree(wm->display, visual, cmap, &wm->titlebar_color); + XftColorFree(wm->display, visual, cmap, &wm->titlebar_focused_color); + XftColorFree(wm->display, visual, cmap, &wm->titlebar_text_color); + XftFontClose(wm->display, wm->titlebar_font); + XCloseDisplay(wm->display); exit(EXIT_SUCCESS); diff --git a/src/wm.h b/src/wm.h index fd27f16..36fea10 100644 --- a/src/wm.h +++ b/src/wm.h @@ -29,6 +29,7 @@ along with this program. If not, see . #include #include #include +#include #include #include #include @@ -126,6 +127,11 @@ struct Wm { Config config; + XftColor titlebar_color; + XftColor titlebar_focused_color; + XftFont *titlebar_font; + XftColor titlebar_text_color; + bool running; bool log_after_maprequest; int socket_fd;