diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a7ec5ba..8975ecb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,7 @@ project(${APP_NAME} LANGUAGES C ) -add_executable(${APP_NAME} main.c utils.c buffer.c backtrace.c) +add_executable(${APP_NAME} main.c utils.c buffer.c backtrace.c monitor.c client.c) # use C23 set_property(TARGET ${APP_NAME} PROPERTY C_STANDARD 23) @@ -31,6 +31,9 @@ pkg_check_modules(deps REQUIRED xcb xcb-aux + xcb-randr + xcb-xfixes + xcb-xinerama ) target_include_directories(${APP_NAME} SYSTEM diff --git a/src/bar.h b/src/bar.h new file mode 100644 index 0000000..3f59c93 --- /dev/null +++ b/src/bar.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/src/base.h b/src/base.h new file mode 100644 index 0000000..a748914 --- /dev/null +++ b/src/base.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +typedef struct area_t { + int16_t x, y; + uint16_t width, height; +} area_t; + +typedef struct extent_in_bar_t { + int16_t start; + int16_t end; +} extent_in_bar_t; diff --git a/src/client.c b/src/client.c new file mode 100644 index 0000000..a8c4739 --- /dev/null +++ b/src/client.c @@ -0,0 +1,17 @@ +#include "client.h" + +void client_scan(void) {} +void client_focus(client_t *client) {} +void client_stack_raise(client_t *client) {} +void client_move_to(client_t *client, int16_t x, int16_t y) {} +void client_resize(client_t *client, uint16_t width, uint16_t height) {} +void client_change_border_color(client_t *client, color_t *color) {} +void client_change_border_width(client_t *client, uint16_t border_width) {} +void client_set_floating(client_t *client, bool floating) {} +void client_set_fullscreen(client_t *client, bool fullscreen) {} +void client_set_maximize(client_t *client, bool maximize) {} +void client_set_minimize(client_t *client, bool minimize) {} +void client_set_class_instance(client_t *client, const char *class, + const char *instance) {} +bool client_is_visible(client_t *client) { return false; } +void client_send_to_tag(client_t *client, tag_t *tag) {} diff --git a/src/client.h b/src/client.h new file mode 100644 index 0000000..603b67d --- /dev/null +++ b/src/client.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include "color.h" +#include "types.h" + +void client_scan(void); +void client_focus(client_t *client); +void client_stack_raise(client_t *client); +void client_move_to(client_t *client, int16_t x, int16_t y); +void client_resize(client_t *client, uint16_t width, uint16_t height); +void client_change_border_color(client_t *client, color_t *color); +void client_change_border_width(client_t *client, uint16_t border_width); +void client_set_floating(client_t *client, bool floating); +void client_set_fullscreen(client_t *client, bool fullscreen); +void client_set_maximize(client_t *client, bool maximize); +void client_set_minimize(client_t *client, bool minimize); +void client_set_class_instance(client_t *client, const char *class, + const char *instance); +bool client_is_visible(client_t *client); +void client_send_to_tag(client_t *client, tag_t *tag); diff --git a/src/color.h b/src/color.h new file mode 100644 index 0000000..746261c --- /dev/null +++ b/src/color.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +typedef struct color_t { + uint32_t rgba; /* use for human reading */ + uint32_t argb; /* use for xcb */ + + /* channels of color, use for cairo */ + double red; /* red channel */ + double green; /* green channel */ + double blue; /* blue channel */ + double alpha; /* alpha channel */ +} color_t; + +/** + * @brief parsing color represented in hexadecimal format + * @param hex color represented in hexadecimal format, the supported format + have: RGB/RGBA/RRGGBB/RRGGBBAA/#RGB/#RGBA/#RRGGBB/#RRGGBBAA + * @param color return the parsed color + */ +void parse_color(const char *hex, color_t *const color); diff --git a/src/draw.h b/src/draw.h new file mode 100644 index 0000000..45dcbb0 --- /dev/null +++ b/src/draw.h @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/src/main.c b/src/main.c index 18dbf8a..9ea6cc6 100644 --- a/src/main.c +++ b/src/main.c @@ -2,15 +2,22 @@ #include #include #include +#include +#include #include #include #include +#include #include #include +#include +#include #include #include "backtrace.h" #include "buffer.h" +#include "client.h" +#include "monitor.h" #include "types.h" #include "utils.h" @@ -82,6 +89,22 @@ static void check_other_wm(void) { global_state.screen = screen; } +static void check_xcb_extensions(void) { + xcb_prefetch_extension_data(global_state.xcb_conn, &xcb_xfixes_id); + xcb_prefetch_extension_data(global_state.xcb_conn, &xcb_xinerama_id); + xcb_prefetch_extension_data(global_state.xcb_conn, &xcb_randr_id); + + const xcb_query_extension_reply_t *query; + query = xcb_get_extension_data(global_state.xcb_conn, &xcb_xfixes_id); + global_state.have_xfixes = query && query->present; + + query = xcb_get_extension_data(global_state.xcb_conn, &xcb_xinerama_id); + global_state.have_xinerama = query && query->present; + + query = xcb_get_extension_data(global_state.xcb_conn, &xcb_randr_id); + global_state.have_randr = query && query->present; +} + int main(int argc, char *argv[]) { p_clear(&global_state, 1); @@ -105,6 +128,10 @@ int main(int argc, char *argv[]) { sigaction(SIGCHLD, &sa, 0); check_other_wm(); + check_xcb_extensions(); + + monitor_scan(); + client_scan(); if (global_state.loop == NULL) { global_state.loop = g_main_loop_new(NULL, FALSE); diff --git a/src/monitor.c b/src/monitor.c new file mode 100644 index 0000000..0260f74 --- /dev/null +++ b/src/monitor.c @@ -0,0 +1,5 @@ +#include "monitor.h" + +void monitor_scan(void) {} + +void monitor_draw_bar(monitor_t *monitor) {} diff --git a/src/monitor.h b/src/monitor.h new file mode 100644 index 0000000..42cc4de --- /dev/null +++ b/src/monitor.h @@ -0,0 +1,6 @@ +#pragma once + +#include "types.h" + +void monitor_scan(void); +void monitor_draw_bar(monitor_t *monitor); diff --git a/src/types.h b/src/types.h index 00e6320..9e96fca 100644 --- a/src/types.h +++ b/src/types.h @@ -1,16 +1,85 @@ #pragma once #include +#include #include #include +#include "base.h" +#include "color.h" + +typedef struct client_t client_t; +typedef struct monitor_t monitor_t; +typedef struct tag_t tag_t; +typedef struct task_in_tag_t task_in_tag_t; + +struct client_t { + client_t *stack_next; + client_t *next; + tag_t *tag; + + area_t geometry; + color_t border_color; + uint16_t border_width; + + bool floating; + bool fullscreen; + bool maximize; + bool minimize; + bool sticky; + + char *name; + char *class; + char *instance; + + xcb_window_t transient_for_window; + xcb_window_t frame_window; + xcb_window_t window; +}; + +struct monitor_t { + monitor_t *next; + area_t geometry; + area_t workarea; + tag_t *tag_list; + tag_t *selected_tag; + + xcb_window_t bar_window; +}; + +struct tag_t { + uint32_t index; /* index in all tags */ + uint32_t mask; + extent_in_bar_t bar_extent; + tag_t *next; + char *name; + monitor_t *monitor; + task_in_tag_t *task_list; +}; + +struct task_in_tag_t { + client_t *client; + task_in_tag_t *next; + area_t geometry; + extent_in_bar_t bar_extent; +}; + typedef struct global_state_t { bool need_restart; GMainLoop *loop; + client_t *client_list; + client_t *client_stack_list; + client_t *client_focused; + monitor_t *monitor_list; + monitor_t *current_monitor; + xcb_connection_t *xcb_conn; xcb_screen_t *screen; int default_screen; + bool have_xfixes; + bool have_xinerama; + bool have_randr; } global_state_t; extern global_state_t global_state; diff --git a/src/xwindow.h b/src/xwindow.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/src/xwindow.h @@ -0,0 +1 @@ +#pragma once