Compare commits
3 Commits
f8fe84f839
...
af4b373478
Author | SHA1 | Date | |
---|---|---|---|
af4b373478 | |||
760368942a | |||
0006a90c86 |
3
Makefile
3
Makefile
@ -3,7 +3,8 @@ EXT=.c
|
|||||||
FLAGS=-O0 -g
|
FLAGS=-O0 -g
|
||||||
DEBUG_FLAGS=-DDEBUG -fsanitize=undefined -fsanitize=address
|
DEBUG_FLAGS=-DDEBUG -fsanitize=undefined -fsanitize=address
|
||||||
DEPFLAGS=-MD -MP
|
DEPFLAGS=-MD -MP
|
||||||
LIBS=$(shell pkg-config --libs xcb x11 xinerama json-c)
|
LIBS=$(shell pkg-config --libs xcb x11 xinerama xft json-c cmocka)
|
||||||
|
FLAGS+=$(shell pkg-config --cflags xcb x11 xinerama xft json-c cmocka)
|
||||||
EXEC_NAME=wm
|
EXEC_NAME=wm
|
||||||
|
|
||||||
OBJDIR=obj
|
OBJDIR=obj
|
||||||
|
41
src/client.c
41
src/client.c
@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "wm.h"
|
#include "wm.h"
|
||||||
|
#include <X11/Xft/Xft.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -162,6 +163,7 @@ void wm_client_hide(Wm *wm, Client *c)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
c->hidden = true;
|
c->hidden = true;
|
||||||
|
XUnmapWindow(wm->display, c->frame);
|
||||||
XUnmapWindow(wm->display, c->window);
|
XUnmapWindow(wm->display, c->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +175,7 @@ void wm_client_show(Wm *wm, Client *c)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
c->hidden = false;
|
c->hidden = false;
|
||||||
|
XMapWindow(wm->display, c->frame);
|
||||||
XMapWindow(wm->display, c->window);
|
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);
|
TreeNode *node = wm_treenode_ptr_find_client_node(c->ws->tree, c);
|
||||||
c->ws->focused_node = node;
|
c->ws->focused_node = node;
|
||||||
wm_monitor_clients_border(wm, c->m);
|
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)
|
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)
|
if (XSendEvent(wm->display, c->window, false, NoEventMask, &event) != Success)
|
||||||
XKillClient(wm->display, c->window);
|
XKillClient(wm->display, c->window);
|
||||||
|
|
||||||
|
XDestroyWindow(wm->display, c->frame);
|
||||||
|
|
||||||
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_client_free(wm, c);
|
||||||
@ -470,3 +476,38 @@ bool wm_client_is_focused(Wm *wm, Client *c)
|
|||||||
|
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
|
@ -38,6 +38,7 @@ struct Client {
|
|||||||
bool hidden;
|
bool hidden;
|
||||||
Monitor *m;
|
Monitor *m;
|
||||||
Window window;
|
Window window;
|
||||||
|
Window frame;
|
||||||
Client *prev;
|
Client *prev;
|
||||||
Client *next;
|
Client *next;
|
||||||
char *name;
|
char *name;
|
||||||
@ -72,6 +73,7 @@ void wm_client_border_focused(Wm* wm, Client *c);
|
|||||||
void wm_monitor_clients_border(Wm* wm, Monitor *m);
|
void wm_monitor_clients_border(Wm* wm, Monitor *m);
|
||||||
bool wm_client_is_focused(Wm* wm, Client *c);
|
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
|
#endif
|
||||||
|
30
src/config.c
30
src/config.c
@ -57,10 +57,15 @@ static const KeybindFunctionCommand __wm_keybind_commands[] = {
|
|||||||
void wm_cfg_init_def(Config *config)
|
void wm_cfg_init_def(Config *config)
|
||||||
{
|
{
|
||||||
config->ms_p = 0.5;
|
config->ms_p = 0.5;
|
||||||
strncpy(config->border_col, "#222222", CONFIG_COLOR_MAX);
|
strcpy(config->border_col, "#222222");
|
||||||
strncpy(config->focused_border_col, "#444444", CONFIG_COLOR_MAX);
|
strcpy(config->focused_border_col, "#444444");
|
||||||
config->border_width = 2;
|
config->border_width = 2;
|
||||||
config->focus_on_motion = true;
|
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);
|
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,
|
(ConfigCommand) {.string = "focus_on_motion", .arg_count = 1,
|
||||||
.cfg_var_offset[0] = offsetof(Config, focus_on_motion),
|
.cfg_var_offset[0] = offsetof(Config, focus_on_motion),
|
||||||
.argc = 0, .arg_type = TYPE_BOOL},
|
.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]);
|
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)
|
KeybindFunction wm_str_to_keybindfunction(const char* str)
|
||||||
{
|
{
|
||||||
DEBUG_PRINT("%s %s\n", __func__, str);
|
DEBUG_PRINT("%s %s\n", __func__, str);
|
||||||
|
|
||||||
char lower[CONFIG_ARGLEN_MAX];
|
char lower[CONFIG_ARGLEN_MAX];
|
||||||
strncpy(lower, str, CONFIG_ARGLEN_MAX);
|
strncpy(lower, str, CONFIG_ARGLEN_MAX);
|
||||||
|
|
||||||
|
@ -87,6 +87,11 @@ typedef struct {
|
|||||||
Keybind *keybinds;
|
Keybind *keybinds;
|
||||||
int kb_count;
|
int kb_count;
|
||||||
bool focus_on_motion;
|
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];
|
char log_path[PATH_MAX];
|
||||||
} Config;
|
} Config;
|
||||||
|
|
||||||
|
@ -94,8 +94,22 @@ void wm_maprequest_handler(Wm *wm, XMapRequestEvent e)
|
|||||||
|
|
||||||
DEBUG_PRINT("%s: client not found, creating client\n", __func__)
|
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);
|
c = wm_client_create(wm, e.window);
|
||||||
RETURN_IF_NULL(c);
|
RETURN_IF_NULL(c);
|
||||||
|
c->frame = frame;
|
||||||
|
|
||||||
wm_ws_tree_insert_client(wm, c->ws, c);
|
wm_ws_tree_insert_client(wm, c->ws, c);
|
||||||
|
|
||||||
|
11
src/tests.c
11
src/tests.c
@ -631,7 +631,11 @@ static void test_wm_config(void **state)
|
|||||||
"focused_border_color #445566\n"
|
"focused_border_color #445566\n"
|
||||||
"border_width 1\n"
|
"border_width 1\n"
|
||||||
"keybind Windows+Alt+Shift+h focus left\n"
|
"keybind Windows+Alt+Shift+h focus left\n"
|
||||||
"focus_on_motion true\n";
|
"show_titlebar true\n"
|
||||||
|
"titlebar_color #001234\n"
|
||||||
|
"titlebar_focused_color #004321\n"
|
||||||
|
"titlebar_font monospace:size=17:antialias=true\n"
|
||||||
|
"titlebar_text_color #aabbcc\n";
|
||||||
|
|
||||||
char tmp[] = "/tmp/XXXXXX";
|
char tmp[] = "/tmp/XXXXXX";
|
||||||
mkstemp(tmp);
|
mkstemp(tmp);
|
||||||
@ -675,6 +679,11 @@ static void test_wm_config(void **state)
|
|||||||
|
|
||||||
assert_true(found_keybind);
|
assert_true(found_keybind);
|
||||||
assert_true(config.focus_on_motion);
|
assert_true(config.focus_on_motion);
|
||||||
|
assert_true(config.show_titlebar);
|
||||||
|
assert_string_equal(config.titlebar_color, "#001234");
|
||||||
|
assert_string_equal(config.titlebar_focused_color, "#004321");
|
||||||
|
assert_string_equal(config.titlebar_font, "monospace:size=17:antialias=true");
|
||||||
|
assert_string_equal(config.titlebar_text_color, "#aabbcc");
|
||||||
|
|
||||||
wm_configfile_free(&file);
|
wm_configfile_free(&file);
|
||||||
wm_keybinds_free(&config);
|
wm_keybinds_free(&config);
|
||||||
|
64
src/wm.c
64
src/wm.c
@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/extensions/Xinerama.h>
|
#include <X11/extensions/Xinerama.h>
|
||||||
|
#include <X11/Xft/Xft.h>
|
||||||
#include "wm.h"
|
#include "wm.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "handler.h"
|
#include "handler.h"
|
||||||
@ -317,11 +318,21 @@ void wm_layout(Wm *wm, Monitor *m)
|
|||||||
|
|
||||||
unsigned int value_mask = CWX | CWY | CWWidth | CWHeight;
|
unsigned int value_mask = CWX | CWY | CWWidth | CWHeight;
|
||||||
XWindowChanges xwc = wm_client_to_xwchanges((client));
|
XWindowChanges xwc = wm_client_to_xwchanges((client));
|
||||||
XConfigureWindow(wm->display, client->window, value_mask, &xwc);
|
XConfigureWindow(wm->display, client->frame, value_mask, &xwc);
|
||||||
wm_client_show(wm, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
XEvent e;
|
||||||
XSync(wm->display, False);
|
XSync(wm->display, False);
|
||||||
@ -444,6 +455,42 @@ void wm_init(Wm *wm)
|
|||||||
// exit(1);
|
// 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_set_supported_atoms(wm);
|
||||||
|
|
||||||
wm->dock = ULONG_MAX;
|
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);
|
XCloseDisplay(wm->display);
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
6
src/wm.h
6
src/wm.h
@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include <X11/Xproto.h>
|
#include <X11/Xproto.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/extensions/Xinerama.h>
|
#include <X11/extensions/Xinerama.h>
|
||||||
|
#include <X11/Xft/Xft.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -126,6 +127,11 @@ struct Wm {
|
|||||||
|
|
||||||
Config config;
|
Config config;
|
||||||
|
|
||||||
|
XftColor titlebar_color;
|
||||||
|
XftColor titlebar_focused_color;
|
||||||
|
XftFont *titlebar_font;
|
||||||
|
XftColor titlebar_text_color;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
bool log_after_maprequest;
|
bool log_after_maprequest;
|
||||||
int socket_fd;
|
int socket_fd;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user