diff --git a/CMakeLists.txt b/CMakeLists.txt index 726b071..42ddb7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ add_executable(${APP_NAME} ${SOURCE_DIR}/core/event.c ${SOURCE_DIR}/core/layer.c ${SOURCE_DIR}/core/layout.c + ${SOURCE_DIR}/core/listeners.c ${SOURCE_DIR}/core/plan.c ${SOURCE_DIR}/core/policy.c ${SOURCE_DIR}/core/rules.c diff --git a/include/zdwm/config.h b/include/zdwm/config.h index bcbe600..075ec64 100644 --- a/include/zdwm/config.h +++ b/include/zdwm/config.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -155,6 +156,57 @@ typedef struct zdwm_api_t { const char *normal, const char *focused ); + + /** @name Listener 注册 + * @{ */ + + void (*subscribe_current_output)( + zdwm_config_builder_t *builder, + zdwm_current_output_id_listener *fn, + void *user_data + ); + void (*subscribe_initial_workspace_list)( + zdwm_config_builder_t *builder, + zdwm_initial_workspace_list *fn, + void *user_data + ); + void (*subscribe_workspace_active)( + zdwm_config_builder_t *builder, + zdwm_workspace_active_updated *fn, + void *user_data + ); + void (*subscribe_layout)( + zdwm_config_builder_t *builder, + zdwm_layout_notify *fn, + void *user_data + ); + void (*subscribe_binding_mode)( + zdwm_config_builder_t *builder, + zdwm_binding_mode_notify *fn, + void *user_data + ); + void (*subscribe_initial_window_list)( + zdwm_config_builder_t *builder, + zdwm_initial_window_list *fn, + void *user_data + ); + void (*subscribe_window_added)( + zdwm_config_builder_t *builder, + zdwm_window_added *fn, + void *user_data + ); + void (*subscribe_window_updated)( + zdwm_config_builder_t *builder, + zdwm_window_updated *fn, + void *user_data + ); + void (*subscribe_window_removed)( + zdwm_config_builder_t *builder, + zdwm_window_removed *fn, + void *user_data + ); + + /** @} */ } zdwm_api_t; /** diff --git a/include/zdwm/listeners.h b/include/zdwm/listeners.h new file mode 100644 index 0000000..9cd30e8 --- /dev/null +++ b/include/zdwm/listeners.h @@ -0,0 +1,63 @@ +#ifndef ZDWM_LISTENERS_H +#define ZDWM_LISTENERS_H + +#include +#include + +typedef void +zdwm_current_output_id_listener(zdwm_output_id_t output_id, void *user_data); + +typedef struct zdwm_workspace_t { + zdwm_output_id_t output_id; + zdwm_workspace_id_t id; + const char *name; /* 不持有内存 */ +} zdwm_workspace_t; +typedef void zdwm_initial_workspace_list( + const zdwm_workspace_t *list, + size_t count, + void *user_data +); +typedef void zdwm_workspace_active_updated( + zdwm_output_id_t output_id, + zdwm_workspace_id_t workspace_id, + void *user_data +); + +typedef struct zdwm_layout_notify_t { + zdwm_workspace_id_t workspace; + zdwm_layout_id_t id; + const char *symbol; /* 不持有内存 */ +} zdwm_layout_notify_t; +typedef void zdwm_layout_notify(zdwm_layout_notify_t layout, void *user_data); + +typedef struct zdwm_binding_mode_notify_t { + bool is_default_mode; + bool is_current_mode; + zdwm_binding_mode_id_t id; + const char *name; /* 不持有内存 */ +} zdwm_binding_mode_notify_t; +typedef void zdwm_binding_mode_notify( + zdwm_binding_mode_notify_t binding_mode, + void *user_data +); + +typedef struct zdwm_window_t { + zdwm_workspace_id_t workspace; + zdwm_window_id_t id; + const char *title; /* 不持有内存 */ + bool focused; + bool urgent; + bool skip_taskbar; +} zdwm_window_t; +typedef void zdwm_initial_window_list( + const zdwm_window_t *list, + size_t count, + void *user_data +); +typedef void zdwm_window_added(const zdwm_window_t *window, void *user_data); +typedef void zdwm_window_updated(const zdwm_window_t *window, void *user_data); +typedef void zdwm_window_removed(zdwm_window_id_t window_id, void *user_data); + +typedef struct zdwm_listeners_t zdwm_listeners_t; + +#endif /* ZDWM_LISTENERS_H */ diff --git a/include/zdwm/types.h b/include/zdwm/types.h index b5a3929..3a2bbea 100644 --- a/include/zdwm/types.h +++ b/include/zdwm/types.h @@ -7,6 +7,7 @@ extern "C" { #endif +typedef uint32_t zdwm_output_id_t; typedef uint32_t zdwm_layout_id_t; typedef uint32_t zdwm_window_id_t; typedef uint32_t zdwm_workspace_id_t; diff --git a/src/config/runtime_config.c b/src/config/runtime_config.c index 3aaff63..0b6c391 100644 --- a/src/config/runtime_config.c +++ b/src/config/runtime_config.c @@ -11,6 +11,7 @@ #include "config/loader.h" #include "core/binding.h" #include "core/layout.h" +#include "core/listeners.h" #include "core/rules.h" #include "core/runtime.h" #include "core/types.h" @@ -28,6 +29,7 @@ struct zdwm_config_builder_t { size_t output_count; border_config_t border; binding_table_t *binding_table; + listeners_t listeners; }; void runtime_config_cleanup(runtime_init_desc_t *desc) { @@ -196,6 +198,87 @@ static void runtime_config_set_border_config( color_parse(focused, &builder->border.focused_color); } +static void runtime_config_subscribe_current_output( + zdwm_config_builder_t *builder, + zdwm_current_output_id_listener *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_output_listener(&builder->listeners, fn, user_data); +} + +static void runtime_config_subscribe_initial_workspace_list( + zdwm_config_builder_t *builder, + zdwm_initial_workspace_list *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_initial_workspace_listener(&builder->listeners, fn, user_data); +} + +static void runtime_config_subscribe_workspace_active( + zdwm_config_builder_t *builder, + zdwm_workspace_active_updated *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_active_workspace_listener(&builder->listeners, fn, user_data); +} + +static void runtime_config_subscribe_layout( + zdwm_config_builder_t *builder, + zdwm_layout_notify *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_layout_notify(&builder->listeners, fn, user_data); +} + +static void runtime_config_subscribe_binding_mode( + zdwm_config_builder_t *builder, + zdwm_binding_mode_notify *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_binding_mode_notify(&builder->listeners, fn, user_data); +} + +static void runtime_config_subscribe_initial_window_list( + zdwm_config_builder_t *builder, + zdwm_initial_window_list *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_initial_window_listener(&builder->listeners, fn, user_data); +} + +static void runtime_config_subscribe_window_added( + zdwm_config_builder_t *builder, + zdwm_window_added *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_window_added_listener(&builder->listeners, fn, user_data); +} + +static void runtime_config_subscribe_window_updated( + zdwm_config_builder_t *builder, + zdwm_window_updated *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_window_updated_listener(&builder->listeners, fn, user_data); +} + +static void runtime_config_subscribe_window_removed( + zdwm_config_builder_t *builder, + zdwm_window_removed *fn, + void *user_data +) { + if (!builder || !fn) return; + listeners_add_window_removed_listener(&builder->listeners, fn, user_data); +} + static bool config_builder_finish( zdwm_config_builder_t *builder, runtime_init_desc_t *out @@ -210,11 +293,13 @@ static bool config_builder_finish( out->binding_table = builder->binding_table; out->workspaces = builder->workspaces; out->workspace_count = builder->workspace_count; + out->listeners = builder->listeners; builder->binding_table = nullptr; builder->workspaces = nullptr; builder->workspace_count = 0; builder->workspace_capacity = 0; builder->output_count = 0; + p_clear(&builder->listeners, 1); return true; } @@ -245,6 +330,18 @@ static bool runtime_config_build( .set_default_mode = runtime_config_set_default_mode, .set_initial_mode = runtime_config_set_initial_mode, .set_border_config = runtime_config_set_border_config, + + .subscribe_current_output = runtime_config_subscribe_current_output, + .subscribe_initial_workspace_list = + runtime_config_subscribe_initial_workspace_list, + .subscribe_workspace_active = runtime_config_subscribe_workspace_active, + .subscribe_layout = runtime_config_subscribe_layout, + .subscribe_binding_mode = runtime_config_subscribe_binding_mode, + .subscribe_initial_window_list = + runtime_config_subscribe_initial_window_list, + .subscribe_window_added = runtime_config_subscribe_window_added, + .subscribe_window_updated = runtime_config_subscribe_window_updated, + .subscribe_window_removed = runtime_config_subscribe_window_removed, }; bool ok = setup(&api, &builder, outputs, output_count) && config_builder_finish(&builder, out); diff --git a/src/core/listeners.c b/src/core/listeners.c new file mode 100644 index 0000000..472e412 --- /dev/null +++ b/src/core/listeners.c @@ -0,0 +1,83 @@ +#include "core/listeners.h" + +#include "base/array.h" + +#define ADD_LISTENER(FIELD) \ + auto list = &listeners->FIELD; \ + auto item = array_push(list->items, list->count, list->capacity); \ + item->fn = fn; \ + item->user_data = user_data + +void listeners_add_output_listener( + listeners_t *listeners, + zdwm_current_output_id_listener fn, + void *user_data +) { + ADD_LISTENER(output_listeners); +} + +void listeners_add_initial_workspace_listener( + listeners_t *listeners, + zdwm_initial_workspace_list fn, + void *user_data +) { + ADD_LISTENER(initial_workspace_listeners); +} + +void listeners_add_active_workspace_listener( + listeners_t *listeners, + zdwm_workspace_active_updated fn, + void *user_data +) { + ADD_LISTENER(active_workspace_listeners); +} + +void listeners_add_layout_notify( + listeners_t *listeners, + zdwm_layout_notify fn, + void *user_data +) { + ADD_LISTENER(layout_listeners); +} + +void listeners_add_binding_mode_notify( + listeners_t *listeners, + zdwm_binding_mode_notify fn, + void *user_data +) { + ADD_LISTENER(binding_mode_listeners); +} + +void listeners_add_initial_window_listener( + listeners_t *listeners, + zdwm_initial_window_list fn, + void *user_data +) { + ADD_LISTENER(initial_window_listeners); +} + +void listeners_add_window_added_listener( + listeners_t *listeners, + zdwm_window_added fn, + void *user_data +) { + ADD_LISTENER(window_added_listeners); +} + +void listeners_add_window_updated_listener( + listeners_t *listeners, + zdwm_window_updated fn, + void *user_data +) { + ADD_LISTENER(window_updated_listeners); +} + +void listeners_add_window_removed_listener( + listeners_t *listeners, + zdwm_window_removed fn, + void *user_data +) { + ADD_LISTENER(window_removed_listeners); +} + +#undef ADD_LISTENER diff --git a/src/core/listeners.h b/src/core/listeners.h new file mode 100644 index 0000000..061c6d2 --- /dev/null +++ b/src/core/listeners.h @@ -0,0 +1,89 @@ +#pragma once + +#include +#include + +#define ITEM(NAME, FN_TYPE) \ + typedef struct NAME##_listener_item_t { \ + FN_TYPE *fn; \ + void *user_data; \ + } NAME##_listener_item_t + +#define LISTENERS(NAME, FN_TYPE) \ + ITEM(NAME, FN_TYPE); \ + typedef struct NAME##_listeners_t { \ + NAME##_listener_item_t *items; \ + size_t count; \ + size_t capacity; \ + } NAME##_listeners_t + +LISTENERS(output, zdwm_current_output_id_listener); +LISTENERS(initial_workspace_list, zdwm_initial_workspace_list); +LISTENERS(workspace_active, zdwm_workspace_active_updated); +LISTENERS(layout, zdwm_layout_notify); +LISTENERS(binding_mode, zdwm_binding_mode_notify); +LISTENERS(initial_window_list, zdwm_initial_window_list); +LISTENERS(window_added, zdwm_window_added); +LISTENERS(window_updated, zdwm_window_updated); +LISTENERS(window_removed, zdwm_window_removed); + +#undef ITEM +#undef LISTENERS + +typedef struct zdwm_listeners_t { + output_listeners_t output_listeners; + initial_workspace_list_listeners_t initial_workspace_listeners; + workspace_active_listeners_t active_workspace_listeners; + layout_listeners_t layout_listeners; + binding_mode_listeners_t binding_mode_listeners; + initial_window_list_listeners_t initial_window_listeners; + window_added_listeners_t window_added_listeners; + window_updated_listeners_t window_updated_listeners; + window_removed_listeners_t window_removed_listeners; +} listeners_t; + +void listeners_add_output_listener( + listeners_t *listeners, + zdwm_current_output_id_listener fn, + void *user_data +); +void listeners_add_initial_workspace_listener( + listeners_t *listeners, + zdwm_initial_workspace_list fn, + void *user_data +); +void listeners_add_active_workspace_listener( + listeners_t *listeners, + zdwm_workspace_active_updated fn, + void *user_data +); +void listeners_add_layout_notify( + listeners_t *listeners, + zdwm_layout_notify fn, + void *user_data +); +void listeners_add_binding_mode_notify( + listeners_t *listeners, + zdwm_binding_mode_notify fn, + void *user_data +); +void listeners_add_initial_window_listener( + listeners_t *listeners, + zdwm_initial_window_list fn, + void *user_data +); +void listeners_add_window_added_listener( + listeners_t *listeners, + zdwm_window_added fn, + void *user_data +); +void listeners_add_window_updated_listener( + listeners_t *listeners, + zdwm_window_updated fn, + void *user_data +); +void listeners_add_window_removed_listener( + listeners_t *listeners, + zdwm_window_removed fn, + void *user_data +); diff --git a/src/core/runtime.c b/src/core/runtime.c index c8944b7..f2f7aac 100644 --- a/src/core/runtime.c +++ b/src/core/runtime.c @@ -62,9 +62,11 @@ bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc) { runtime->border = desc->border; runtime->config_module_handle = desc->config_module_handle; runtime->binding_table = desc->binding_table; + runtime->listeners = desc->listeners; desc->backend = nullptr; desc->config_module_handle = nullptr; desc->binding_table = nullptr; + p_clear(&desc->listeners, 1); state_init( &runtime->state, diff --git a/src/core/runtime.h b/src/core/runtime.h index 42a0037..b923685 100644 --- a/src/core/runtime.h +++ b/src/core/runtime.h @@ -7,6 +7,7 @@ #include "core/binding.h" #include "core/command_buffer.h" #include "core/layout.h" +#include "core/listeners.h" #include "core/plan.h" #include "core/rules.h" #include "core/state.h" @@ -24,6 +25,7 @@ typedef struct runtime_init_desc_t { size_t workspace_count; void *config_module_handle; binding_table_t *binding_table; + listeners_t listeners; } runtime_init_desc_t; typedef struct zdwm_runtime_t { @@ -40,6 +42,7 @@ typedef struct zdwm_runtime_t { backend_t *backend; void *config_module_handle; binding_table_t *binding_table; + listeners_t listeners; } runtime_t; bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc); diff --git a/src/core/types.h b/src/core/types.h index b44b143..331de7b 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -10,7 +10,7 @@ typedef zdwm_layout_id_t layout_id_t; typedef zdwm_window_id_t window_id_t; typedef zdwm_workspace_id_t workspace_id_t; -typedef uint32_t output_id_t; +typedef zdwm_output_id_t output_id_t; typedef zdwm_rect_t rect_t; typedef zdwm_output_info_t output_info_t;