diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d961439..523a18c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,7 +15,7 @@ project(${APP_NAME} LANGUAGES C ) -add_executable(${APP_NAME} main.c utils.c) +add_executable(${APP_NAME} main.c utils.c config.c) # use C17 set_property(TARGET ${APP_NAME} PROPERTY C_STANDARD 17) @@ -24,6 +24,7 @@ target_include_directories(${APP_NAME} PRIVATE "${SOURCE_DIR}/include") find_package(PkgConfig REQUIRED) +pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(XCB REQUIRED xcb xcb-cursor @@ -35,10 +36,18 @@ pkg_check_modules(XCB REQUIRED xcb-xinerama xcb-xrm ) -target_include_directories(${APP_NAME} SYSTEM PUBLIC ${XCB_INCLUDE_DIRS}) + +target_include_directories(${APP_NAME} SYSTEM PUBLIC + ${GLIB_INCLUDE_DIRS} + ${XCB_INCLUDE_DIRS} +) add_subdirectory(xcb) -target_link_libraries(${APP_NAME} ${LIB_XCB_NAME}) + +target_link_libraries(${APP_NAME} + ${GLIB_LIBRARIES} + ${LIB_XCB_NAME} +) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/app.h.in" diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..d0b18c2 --- /dev/null +++ b/src/config.c @@ -0,0 +1,6 @@ +#include "config.h" + +#include + +/* 壁纸列表,支持通配符和 shell 环境变量拼接,最后以 NULL 结尾 */ +const char *wallpager_list[] = {NULL}; diff --git a/src/include/config.h b/src/include/config.h new file mode 100644 index 0000000..0375e13 --- /dev/null +++ b/src/include/config.h @@ -0,0 +1,3 @@ +#pragma once + +extern const char *wallpager_list[]; diff --git a/src/include/types.h b/src/include/types.h new file mode 100644 index 0000000..83cfacb --- /dev/null +++ b/src/include/types.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include + +typedef struct monitor_t monitor_t; +typedef struct client_t client_t; + +typedef struct layout_t { + const char *symbol; + void (*arrange)(monitor_t *monitor); +} layout_t; + +#define TAG_SYMBOL_LENGTH 32 + +/* 避免引入 xcb 头文件 */ +typedef uint32_t xcb_window_t; + +struct monitor_t { + uint32_t index; + int32_t monitor_x, monitor_y, window_x, window_y; + uint32_t monitor_width, monitor_height, window_width, window_height; + + uint32_t selected_tag; + uint32_t tag_count; + char (*tags)[TAG_SYMBOL_LENGTH]; + + /* 为了避免引入 cairo 相关头文件,这里用 void * + * 指针代替实际的指针类型,使用时强转为相应指针类型使用即可 */ + void *surface; /* cairo_surface_t */ + void *cr; /* cairo_t */ + + const layout_t *layout; + monitor_t *next; + + client_t *clients; + client_t *clients_stack; + client_t *selected_client; + + xcb_window_t bar_window; +}; + +struct client_t { + char name[256]; + int32_t x, y; + uint32_t width, height, border_width; + uint32_t tags; + bool fullscreen; + bool floating; + + monitor_t *monitor; + client_t *next; + client_t *stack_next; + + xcb_window_t window; +}; + +typedef struct wallpaper_config_t { + uint32_t count; + char **path_list; +} wallpaper_config_t; diff --git a/src/include/utils.h b/src/include/utils.h index ed860bf..830329f 100644 --- a/src/include/utils.h +++ b/src/include/utils.h @@ -1,8 +1,11 @@ #pragma once +#include #include #define LENGTH(X) (sizeof(X) / sizeof(X)[0]) void die(const char *format, ...); void *ecalloc(size_t number_of_member, size_t member_size); + +bool file_exist(const char *path); diff --git a/src/main.c b/src/main.c index 2292183..ad7d571 100644 --- a/src/main.c +++ b/src/main.c @@ -1,26 +1,120 @@ +#include +#include #include #include #include +#include +#include +#include "config.h" +#include "types.h" #include "utils.h" #include "xcb.h" +static void init_monitors(void); +static wallpaper_config_t *parse_wallpaper_config(const char **wallpapers); +static void free_wallpaper_config(wallpaper_config_t *wallpaper_config); +static void cleanup(void); + +static monitor_t *monitors = NULL; +static wallpaper_config_t *wallpaper_config = NULL; + +void init_monitors(void) { + monitor_rect_t *mr = detect_monitor_rect(); + uint32_t i = 0; + while (mr) { + monitor_t *m = ecalloc(1, sizeof(monitor_t)); + m->monitor_x = mr->x; + m->monitor_y = mr->y; + m->monitor_width = mr->width; + m->monitor_height = mr->height; + m->index = i; + + printf("mon[%u]: x: %d, y: %d, w: %u, h: %u\n", i, mr->x, mr->y, mr->width, + mr->height); + + if (!i) monitors = m; + + i++; + monitor_rect_t *next_mr = mr->next; + free(mr); + mr = next_mr; + } +} + +wallpaper_config_t *parse_wallpaper_config(const char **wallpapers) { + if (!wallpapers) return NULL; + + wallpaper_config_t *wc = ecalloc(1, sizeof(wallpaper_config_t)); + + GStrvBuilder *builder = g_strv_builder_new(); + for (int i = 0; wallpapers && wallpapers[i]; i++) { + wordexp_t p; + if (wordexp(wallpapers[i], &p, 0)) continue; + + for (size_t i = 0; i < p.we_wordc; i++) { + size_t len = strlen(p.we_wordv[i]) + 1; + char *realpath = ecalloc(len, sizeof(char)); + strncpy(realpath, p.we_wordv[i], len); + g_strstrip(realpath); + if (file_exist(realpath)) g_strv_builder_add(builder, realpath); + + free(realpath); + } + wordfree(&p); + } + + wc->path_list = g_strv_builder_unref_to_strv(builder); + wc->count = g_strv_length(wc->path_list); + if (wc->count) return wc; + + free_wallpaper_config(wc); + return NULL; +} + +void free_wallpaper_config(wallpaper_config_t *wallpaper_config) { + if (!wallpaper_config) return; + + g_strfreev(wallpaper_config->path_list); + free(wallpaper_config); +} + +void cleanup(void) { + clean_xcb(); + + free_wallpaper_config(wallpaper_config); + wallpaper_config = NULL; + + monitor_t *m = monitors; + client_t *c = m->clients; + while (m) { + while (c) { + client_t *tc = c->next; + free(c); + c = tc; + } + monitor_t *tm = m->next; + free(m); + m = tm; + } + monitors = NULL; +} + int main(int argc, char *argv[]) { if (has_other_wm_running()) { die("another window manager is already running"); } - { - monitor_rect_t *mr = detect_monitor_rect(); - uint32_t i = 0; - while (mr) { - printf("mon[%u]: x: %d, y: %d, w: %u, h: %u\n", i, mr->x, mr->y, - mr->width, mr->height); - mr = mr->next; - free(mr); + wallpaper_config = parse_wallpaper_config(wallpager_list); + if (wallpaper_config) { + printf("wallpaper count: %u\n", wallpaper_config->count); + for (uint32_t i = 0; i < wallpaper_config->count; i++) { + printf("wallpaper[%02u]: %s\n", i, wallpaper_config->path_list[i]); } } + init_monitors(); + window_list_t *window_list = scan_window_list(); if (window_list) { for (uint32_t i = 0; i < window_list->count; i++) { @@ -31,7 +125,7 @@ int main(int argc, char *argv[]) { } free_window_list(window_list); - clean_xcb(); + cleanup(); return 0; } diff --git a/src/utils.c b/src/utils.c index 7755a07..d911534 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,9 +1,11 @@ #include "utils.h" #include +#include #include #include #include +#include void die(const char *fmt, ...) { va_list ap; @@ -30,3 +32,8 @@ void *ecalloc(size_t number_of_member, size_t member_size) { return p; } + +bool file_exist(const char *path) { + if (!path || !*path) return false; + return access(path, R_OK) == 0; +}