diff --git a/src/backend/x11/backend.c b/src/backend/x11/backend.c index 7c00e73..efc3226 100644 --- a/src/backend/x11/backend.c +++ b/src/backend/x11/backend.c @@ -22,8 +22,10 @@ #include "base/macros.h" #include "base/memory.h" #include "base/window_list.h" +#include "core/event.h" #include "core/plan.h" #include "core/types.h" +#include "core/window.h" #include "internal.h" typedef struct atom_item_t { @@ -625,3 +627,54 @@ bool backend_apply_effect( xcb_flush(backend->conn); return true; } + +backend_scan_result_t *backend_scan_windows(backend_t *backend) { + auto conn = backend->conn; + auto root = backend->screen->root; + auto cookie = xcb_query_tree_unchecked(conn, root); + auto reply = xcb_query_tree_reply(conn, cookie, nullptr); + if (!reply) return nullptr; + + auto length = xcb_query_tree_children_length(reply); + if (!length) { + p_delete(&reply); + return nullptr; + } + + auto list = xcb_query_tree_children(reply); + + backend_scan_result_t *result = p_new(backend_scan_result_t, 1); + + for (int i = 0; i < length; i++) { + auto slot = (window_map_request_event_t *) + array_push(result->windows, result->count, result->capacity); + if (!populate_window_event(backend, list[i], slot)) { + window_layer_props_cleanup(&slot->props); + window_metadata_cleanup(&slot->metadata); + result->count--; + } + } + + p_delete(&reply); + + if (result->count == 0) { + backend_scan_result_destroy(result); + result = nullptr; + return nullptr; + } + + return result; +} + +void backend_scan_result_destroy(backend_scan_result_t *result) { + if (!result) return; + + for (size_t i = 0; i < result->count; i++) { + window_map_request_event_t *ev = &result->windows[i]; + window_layer_props_cleanup(&ev->props); + window_metadata_cleanup(&ev->metadata); + } + + p_delete(&result->windows); + p_delete(&result); +} diff --git a/src/backend/x11/event.c b/src/backend/x11/event.c index 4662354..ef45313 100644 --- a/src/backend/x11/event.c +++ b/src/backend/x11/event.c @@ -91,18 +91,13 @@ static bool urgent_from_states( return false; } -static bool handle_map_request( +bool populate_window_event( backend_t *backend, - event_t *event, - const xcb_map_request_event_t *xcb_event + xcb_window_t window, + window_map_request_event_t *ev ) { - xcb_window_t window = xcb_event->window; - - event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST; - - window_map_request_event_t *ev = &event->as.window_map_request; - ev->window = (window_id_t)window; - ev->transient_for = window_get_transient_for(backend, window); + ev->window = (window_id_t)window; + ev->transient_for = window_get_transient_for(backend, window); xcb_get_window_attributes_reply_t *wa = window_get_attributes(backend, window); @@ -167,6 +162,19 @@ static bool handle_map_request( return true; } +static bool handle_map_request( + backend_t *backend, + event_t *event, + const xcb_map_request_event_t *xcb_event +) { + event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST; + return populate_window_event( + backend, + xcb_event->window, + &event->as.window_map_request + ); +} + static bool handle_unmap_notify( backend_t *backend, event_t *event, diff --git a/src/backend/x11/internal.h b/src/backend/x11/internal.h index d1cefa4..7a19ca7 100644 --- a/src/backend/x11/internal.h +++ b/src/backend/x11/internal.h @@ -7,6 +7,7 @@ #include #include "base/window_list.h" +#include "core/event.h" #define ATOM_LIST(X) \ X(COMPOUND_TEXT) \ @@ -94,3 +95,9 @@ struct backend_t { window_list_t map; window_list_t kill; }; + +bool populate_window_event( + struct backend_t *backend, + xcb_window_t window, + window_map_request_event_t *ev +); diff --git a/src/core/backend.h b/src/core/backend.h index e8c4581..9b5b571 100644 --- a/src/core/backend.h +++ b/src/core/backend.h @@ -37,3 +37,17 @@ bool backend_apply_effect( const effect_t *effects, size_t effect_count ); + +typedef struct backend_scan_result_t { + window_map_request_event_t *windows; + size_t count; + size_t capacity; +} backend_scan_result_t; + +/** + * @brief 扫描已有窗口 + * + * @details 仅扫描窗口并获取其基础信息 + */ +backend_scan_result_t *backend_scan_windows(backend_t *backend); +void backend_scan_result_destroy(backend_scan_result_t *result); diff --git a/src/core/policy.c b/src/core/policy.c index ad42a9f..d5c5476 100644 --- a/src/core/policy.c +++ b/src/core/policy.c @@ -53,6 +53,7 @@ static void route_map_request( const window_map_request_event_t *e, command_buffer_t *out ) { + if (e->override_redirect) return; if (state_window_get(state, e->window)) return; window_layer_type_t layer_type = window_classify_layer(&e->props); diff --git a/src/core/runtime.c b/src/core/runtime.c index 12cde03..b48cad7 100644 --- a/src/core/runtime.c +++ b/src/core/runtime.c @@ -257,20 +257,14 @@ static void runtime_arrange(runtime_t *runtime) { } } -void runtime_run(runtime_t *runtime) { - runtime->running = true; - - backend_t *backend = runtime->backend; - command_buffer_t *command_buffer = &runtime->command_buffer; - plan_t *plan = &runtime->plan; - +policy_context_t policy_context_init(runtime_t *runtime) { policy_context_t ctx = { - .bind_table = runtime->binding_table, - .state = &runtime->state, - .rules = &runtime->rules, - .border = &runtime->border, - .layouts = &runtime->layouts, - .runtime = runtime, + .bind_table = (runtime)->binding_table, + .state = &(runtime)->state, + .rules = &(runtime)->rules, + .border = &(runtime)->border, + .layouts = &(runtime)->layouts, + .runtime = (runtime), .action_api = { .spawn = spawn, .quit = quit, @@ -284,6 +278,46 @@ void runtime_run(runtime_t *runtime) { .cycle_current_output = cycle_current_output, }, }; + return ctx; +} + +void runtime_scan(runtime_t *runtime) { + auto result = backend_scan_windows(runtime->backend); + if (!result) return; + + policy_context_t ctx = policy_context_init(runtime); + + auto backend = runtime->backend; + auto command_buffer = &runtime->command_buffer; + auto plan = &runtime->plan; + + command_buffer_reset(command_buffer); + plan_reset(plan); + + for (size_t i = 0; i < result->count; i++) { + event_t event = { + .type = ZDWM_EVENT_WINDOW_MAP_REQUEST, + .as.window_map_request = result->windows[i], + }; + policy_route_event(&ctx, &event, command_buffer); + } + + policy_apply_command(&ctx, command_buffer, plan); + if (plan->need_relayout) runtime_arrange(runtime); + if (plan->count) backend_apply_effect(backend, plan->effects, plan->count); + + backend_scan_result_destroy(result); + result = nullptr; +} + +void runtime_run(runtime_t *runtime) { + runtime->running = true; + + backend_t *backend = runtime->backend; + command_buffer_t *command_buffer = &runtime->command_buffer; + plan_t *plan = &runtime->plan; + + policy_context_t ctx = policy_context_init(runtime); while (runtime->running) { event_t event = {0}; diff --git a/src/core/runtime.h b/src/core/runtime.h index 0a2f34d..42a0037 100644 --- a/src/core/runtime.h +++ b/src/core/runtime.h @@ -46,4 +46,5 @@ bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc); void runtime_init_desc_cleanup(runtime_init_desc_t *desc); void runtime_shutdown(runtime_t *runtime); void runtime_setup(runtime_t *runtime); +void runtime_scan(runtime_t *runtime); void runtime_run(runtime_t *runtime);