Compare commits

..

4 Commits

13 changed files with 171 additions and 17 deletions

View File

@@ -40,6 +40,7 @@ add_executable(${APP_NAME}
${SOURCE_DIR}/xkb.c ${SOURCE_DIR}/xkb.c
${SOURCE_DIR}/atoms.c ${SOURCE_DIR}/atoms.c
${SOURCE_DIR}/layout.c ${SOURCE_DIR}/layout.c
${SOURCE_DIR}/xres.c
) )
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
@@ -57,6 +58,7 @@ pkg_check_modules(deps REQUIRED
xcb-xfixes xcb-xfixes
xcb-xinerama xcb-xinerama
xcb-xkb xcb-xkb
xcb-xrm
xkbcommon-x11 xkbcommon-x11
cairo cairo

View File

@@ -19,10 +19,10 @@ clean:
${RM} -r $(BUILD_DIR) ${RM} -r $(BUILD_DIR)
run: run:
-$(shell Xephyr :3 -screen 1920x1080 &) -$(shell Xephyr :3 -screen 1920x1080 -dpi `xrdb -get Xft.dpi` &)
run_multiple_screen: run_multiple_screen:
-$(shell Xephyr :3 -screen 1920x1080 -screen 1920x1080 +xinerama &) -$(shell Xephyr :3 -screen 1920x1080 -screen 1920x1080 +xinerama -dpi `xrdb -get Xft.dpi` &)
wm: $(TARGET_NAME) wm: $(TARGET_NAME)
DISPLAY=:3 $(TARGET) DISPLAY=:3 $(TARGET)

View File

@@ -8,6 +8,7 @@
#include <xcb/xproto.h> #include <xcb/xproto.h>
#include "atoms-extern.h" #include "atoms-extern.h"
#include "base.h"
#include "monitor.h" #include "monitor.h"
#include "types.h" #include "types.h"
#include "utils.h" #include "utils.h"
@@ -64,6 +65,7 @@ static void client_add_to_tag(client_t *client, tag_t *tag) {
task->client = client; task->client = client;
task->next = tag->task_list; task->next = tag->task_list;
tag->task_list = task; tag->task_list = task;
task->geometry = client->geometry;
} }
static void client_remove_from_tag(client_t *client, tag_t *tag) { static void client_remove_from_tag(client_t *client, tag_t *tag) {
@@ -110,14 +112,32 @@ static inline void client_update_names(client_t *c) {
xwindow_get_text_property(c->window, _NET_WM_ICON_NAME, &c->net_icon_name); xwindow_get_text_property(c->window, _NET_WM_ICON_NAME, &c->net_icon_name);
} }
static inline void client_init_geometry(client_t *c) {
area_t workarea = c->monitor->workarea;
if (c->geometry.x + client_width(c) > workarea.x + workarea.width) {
c->geometry.x = workarea.x + workarea.width - client_width(c);
}
if (c->geometry.y + client_height(c) > workarea.y + workarea.height) {
c->geometry.y = workarea.y + workarea.height - client_height(c);
}
c->geometry.x = MAX(c->geometry.x, workarea.x);
c->geometry.y = MAX(c->geometry.y, workarea.y);
client_move_to(c, c->geometry.x, c->geometry.y);
client_resize(c, c->geometry.width, c->geometry.height);
client_change_border_color(c, &wm.color_set.active_border_color);
client_change_border_width(c, wm.border_width);
}
void client_manage(xcb_window_t window, void client_manage(xcb_window_t window,
xcb_get_geometry_reply_t *geometry_reply) { xcb_get_geometry_reply_t *geometry_reply) {
client_t *c = p_new(client_t, 1); client_t *c = p_new(client_t, 1);
c->window = window; c->window = window;
c->geometry.x = geometry_reply->x;
client_move_to(c, geometry_reply->x, geometry_reply->y); c->geometry.y = geometry_reply->y;
client_resize(c, geometry_reply->width, geometry_reply->height); c->geometry.width = geometry_reply->width;
client_change_border_width(c, geometry_reply->border_width); c->geometry.height = geometry_reply->height;
c->border_width = geometry_reply->border_width;
{ {
const xcb_params_cw_t params = { const xcb_params_cw_t params = {
@@ -161,6 +181,7 @@ void client_manage(xcb_window_t window,
c->tags = c->monitor->selected_tag->mask; c->tags = c->monitor->selected_tag->mask;
} }
client_init_geometry(c);
client_tags_apply(c); client_tags_apply(c);
} }
@@ -211,12 +232,22 @@ void client_resize(client_t *client, uint16_t width, uint16_t height) {
width, height); width, height);
} }
void client_change_border_color(client_t *client, color_t *color) {
uint16_t mask = XCB_CW_BORDER_PIXEL;
const xcb_params_cw_t params = {.border_pixel = color->argb};
xcb_aux_change_window_attributes(wm.xcb_conn, client->window, mask, &params);
client->border_color = color;
logger("== client 0x%x border color: RGBA(#%08x), ARGB(#%08x)\n",
client->window, color->rgba, color->argb);
}
void client_change_border_width(client_t *client, uint16_t border_width) { void client_change_border_width(client_t *client, uint16_t border_width) {
if (client->border_width == border_width) return; if (client->border_width == border_width) return;
uint16_t mask = XCB_CONFIG_WINDOW_BORDER_WIDTH; uint16_t mask = XCB_CONFIG_WINDOW_BORDER_WIDTH;
const xcb_params_configure_window_t params = {.border_width = border_width}; const xcb_params_configure_window_t params = {.border_width = border_width};
xcb_aux_configure_window(wm.xcb_conn, client->window, mask, &params); xcb_aux_configure_window(wm.xcb_conn, client->window, mask, &params);
client->border_width = border_width; client->border_width = border_width;
logger("== client 0x%x border width: %u\n", client->window, border_width);
} }
void client_update_wm_hints(client_t *client) { void client_update_wm_hints(client_t *client) {

View File

@@ -51,3 +51,10 @@ void client_focus(client_t *client);
void client_stack_raise(client_t *client); void client_stack_raise(client_t *client);
bool client_is_visible(client_t *client); bool client_is_visible(client_t *client);
static inline uint16_t client_width(client_t *c) {
return c->geometry.width + c->border_width * 2;
}
static inline uint16_t client_height(client_t *c) {
return c->geometry.height + c->border_width * 2;
}

View File

@@ -14,6 +14,7 @@ static const int default_dpi = 144;
static const char *const tags[] = { static const char *const tags[] = {
"1", "2", "3", "4", "5", "6", "7", "8", "9", nullptr, "1", "2", "3", "4", "5", "6", "7", "8", "9", nullptr,
}; };
static const uint16_t border_width = 1;
static const uint16_t bar_y_padding = 1; static const uint16_t bar_y_padding = 1;
static const uint16_t tag_x_padding = 10; static const uint16_t tag_x_padding = 10;
@@ -22,6 +23,8 @@ static const char *const tag_bg = "#222222";
static const char *const active_tag_bg = "#005577"; static const char *const active_tag_bg = "#005577";
static const char *const tag_color = "#bbbbbb"; static const char *const tag_color = "#bbbbbb";
static const char *const active_tag_color = "#eeeeee"; static const char *const active_tag_color = "#eeeeee";
static const char *const border_color = "#444444";
static const char *const active_border_color = "#005577";
static const button_t button_list[] = { static const button_t button_list[] = {
{click_tag, modifier_none, button_left, select_tag_of_current_monitor, {0}}, {click_tag, modifier_none, button_left, select_tag_of_current_monitor, {0}},

View File

@@ -2,6 +2,7 @@
#include <stdint.h> #include <stdint.h>
#include "base.h"
#include "client.h" #include "client.h"
#include "types.h" #include "types.h"
#include "utils.h" #include "utils.h"
@@ -10,10 +11,17 @@ void monocle(tag_t *tag) {
logger("== monocle tag: %s start ==\n", tag->name); logger("== monocle tag: %s start ==\n", tag->name);
for (task_in_tag_t *task = tag->task_list; task; task = task->next) { for (task_in_tag_t *task = tag->task_list; task; task = task->next) {
if (!client_need_layout(task->client)) continue; if (!client_need_layout(task->client)) continue;
task->geometry = task->client->monitor->workarea;
logger("== window 0x%x: x: %d, y: %d, width: %u, height: %u\n", uint16_t border_width = task->client->border_width;
task->client->window, task->geometry.x, task->geometry.y, area_t workarea = task->client->monitor->workarea;
task->geometry.width, task->geometry.height); task->geometry.x = workarea.x;
task->geometry.y = workarea.y;
task->geometry.width = workarea.width - border_width * 2;
task->geometry.height = workarea.height - border_width * 2;
logger(
"== window 0x%x: x: %d, y: %d, width: %u, height: %u, border width: %u\n",
task->client->window, task->geometry.x, task->geometry.y,
task->geometry.width, task->geometry.height, border_width);
} }
logger("== monocle tag: %s end ==\n", tag->name); logger("== monocle tag: %s end ==\n", tag->name);
} }

View File

@@ -255,8 +255,8 @@ void monitor_arrange(monitor_t *monitor) {
if (task) { if (task) {
client_apply_task_geometry(c, task); client_apply_task_geometry(c, task);
} else { } else {
int16_t x = -c->geometry.width; int16_t x = -client_width(c);
int16_t y = -c->geometry.height; int16_t y = -client_height(c);
if (x != c->geometry.x || y != c->geometry.y) { if (x != c->geometry.x || y != c->geometry.y) {
client_move_to(c, x, y); client_move_to(c, x, y);
} }

View File

@@ -86,8 +86,11 @@ typedef struct color_set_t {
color_t active_tag_bg; color_t active_tag_bg;
color_t tag_color; color_t tag_color;
color_t active_tag_color; color_t active_tag_color;
color_t border_color;
color_t active_border_color;
} color_set_t; } color_set_t;
typedef struct padding_t { typedef struct padding_t {
uint16_t bar_y;
uint16_t tag_x; uint16_t tag_x;
} padding_t; } padding_t;

View File

@@ -87,3 +87,8 @@ static inline void logger(const char *format, ...) {
#else #else
#define logger(format, ...) printf(format, ##__VA_ARGS__) #define logger(format, ...) printf(format, ##__VA_ARGS__)
#endif #endif
#ifdef MAX
#undef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif

View File

@@ -31,6 +31,7 @@
#include "utils.h" #include "utils.h"
#include "xcursor.h" #include "xcursor.h"
#include "xkb.h" #include "xkb.h"
#include "xres.h"
#include "xwindow.h" #include "xwindow.h"
static void wm_setup_signal(void); static void wm_setup_signal(void);
@@ -40,6 +41,7 @@ static void wm_detect_monitor(void);
static void wm_scan_clients(void); static void wm_scan_clients(void);
static void wm_clean(void); static void wm_clean(void);
static void wm_setup(void); static void wm_setup(void);
static void wm_get_xres_config(void);
static void wm_init_color_set(void); static void wm_init_color_set(void);
static void wm_setup_keybindings(void); static void wm_setup_keybindings(void);
@@ -277,16 +279,18 @@ void wm_clean(void) {
} }
static void wm_setup(void) { static void wm_setup(void) {
wm.padding.tag_x = tag_x_padding;
wm.layout_list = layout_list; wm.layout_list = layout_list;
wm.layout_count = (uint16_t)countof(layout_list); wm.layout_count = (uint16_t)countof(layout_list);
wm_get_xres_config();
wm_init_color_set(); wm_init_color_set();
int font_height = text_init_pango_layout(font_family, font_size, default_dpi); {
wm.bar_height = (uint16_t)font_height + 2 * bar_y_padding; int font_height =
text_init_pango_layout(wm.font_family, wm.font_size, wm.dpi);
logger("font height: %d, bar height: %u\n", font_height, wm.bar_height); wm.bar_height = (uint16_t)font_height + 2 * wm.padding.bar_y;
logger("font height: %d, bar height: %u\n", font_height, wm.bar_height);
}
uint32_t tag_count = 0; uint32_t tag_count = 0;
for (monitor_t *m = wm.monitor_list; m; m = m->next) { for (monitor_t *m = wm.monitor_list; m; m = m->next) {
@@ -330,12 +334,36 @@ static void wm_setup(void) {
xcb_flush(wm.xcb_conn); xcb_flush(wm.xcb_conn);
} }
static void wm_get_xres_config(void) {
xres_init_xrm_db();
wm.dpi = default_dpi;
wm.font_size = font_size;
xres_get_uint32("Xft.dpi", (uint32_t *)&wm.dpi);
xres_get_uint32(APP_NAME ".font_size", (uint32_t *)&wm.font_size);
xres_get_string(APP_NAME ".font_family", &wm.font_family, font_family);
wm.border_width = border_width;
xres_get_uint32(APP_NAME ".border_width", (uint32_t *)&wm.border_width);
wm.padding.bar_y = bar_y_padding;
wm.padding.tag_x = tag_x_padding;
#define NAME APP_NAME ".padding."
xres_get_uint32(NAME "bar_y", (uint32_t *)&wm.padding.bar_y);
xres_get_uint32(NAME "tag_x", (uint32_t *)&wm.padding.tag_x);
#undef NAME
xres_clean();
}
void wm_init_color_set(void) { void wm_init_color_set(void) {
color_parse(bar_bg, &wm.color_set.bar_bg); color_parse(bar_bg, &wm.color_set.bar_bg);
color_parse(tag_bg, &wm.color_set.tag_bg); color_parse(tag_bg, &wm.color_set.tag_bg);
color_parse(active_tag_bg, &wm.color_set.active_tag_bg); color_parse(active_tag_bg, &wm.color_set.active_tag_bg);
color_parse(tag_color, &wm.color_set.tag_color); color_parse(tag_color, &wm.color_set.tag_color);
color_parse(active_tag_color, &wm.color_set.active_tag_color); color_parse(active_tag_color, &wm.color_set.active_tag_color);
color_parse(border_color, &wm.color_set.border_color);
color_parse(active_border_color, &wm.color_set.active_border_color);
} }
void wm_setup_keybindings(void) { void wm_setup_keybindings(void) {

View File

@@ -2,12 +2,14 @@
#include <stdint.h> #include <stdint.h>
#include <xcb/xcb_keysyms.h> #include <xcb/xcb_keysyms.h>
#include <xcb/xcb_xrm.h>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include "types.h" #include "types.h"
typedef struct wm_t { typedef struct wm_t {
padding_t padding; padding_t padding;
uint16_t border_width;
uint16_t bar_height; uint16_t bar_height;
uint16_t layout_count; uint16_t layout_count;
@@ -21,8 +23,13 @@ typedef struct wm_t {
monitor_t *current_monitor; monitor_t *current_monitor;
const layout_t *layout_list; const layout_t *layout_list;
char *font_family;
uint32_t font_size;
uint32_t dpi;
xcb_connection_t *xcb_conn; xcb_connection_t *xcb_conn;
xcb_screen_t *screen; xcb_screen_t *screen;
xcb_xrm_database_t *xrm;
xcb_key_symbols_t *key_symbols; xcb_key_symbols_t *key_symbols;
xcb_window_t wm_check_window; xcb_window_t wm_check_window;
int default_screen; int default_screen;

52
src/xres.c Normal file
View File

@@ -0,0 +1,52 @@
#include "xres.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <xcb/xcb_xrm.h>
#include "wm.h"
void xres_init_xrm_db(void) {
if (wm.xrm) return;
wm.xrm = xcb_xrm_database_from_default(wm.xcb_conn);
}
void xres_clean(void) {
if (!wm.xrm) return;
xcb_xrm_database_free(wm.xrm);
wm.xrm = nullptr;
}
/**
* @brief 获取 Xresources 文件中配置的 long 类型配置并将其转化为 uint32_t 类型
* @param name Xresources 文件中的配置名
* @param value 获取到的结果存放的指针
* @returns 配置获取是否成功,成功返回 true 失败返回 false
*/
bool xres_get_uint32(const char *name, uint32_t *value) {
if (!wm.xrm) return false;
long temp_value = 0;
bool success =
xcb_xrm_resource_get_long(wm.xrm, name, nullptr, &temp_value) == 0;
if (success) *value = (uint32_t)temp_value;
return success;
}
/**
* @brief 读取 Xresources 文件中的字符串配置
* @param name Xresources 文件中的配置名
* @param value 存放读取到的字符串存储的指针的指针,使用完后记得使用
* free(*value) 释放字符串对应的内存
* @param fallback 若 Xresources 解析失败,则使用这个默认值
*/
void xres_get_string(const char *name, char **value, const char *fallback) {
if (!wm.xrm) return;
if (!xcb_xrm_resource_get_string(wm.xrm, name, nullptr, value)) return;
*value = strdup(fallback);
}

8
src/xres.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include <stdint.h>
void xres_init_xrm_db(void);
void xres_clean(void);
bool xres_get_uint32(const char *name, uint32_t *value);
void xres_get_string(const char *name, char **value, const char *fallback);