feat: 让 bar 支持点击触发动作

This commit is contained in:
2026-06-23 06:57:38 +08:00
parent 29e0f1e2dc
commit 42bddf5ac7
5 changed files with 86 additions and 2 deletions

View File

@@ -5,6 +5,7 @@
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <zdwm/action.h>
#include <zdwm/bar.h>
#include <zdwm/types.h>
@@ -394,3 +395,49 @@ bool bar_draw(bar_t *bar) {
return changed;
}
static inline bool
bar_item_click(zdwm_bar_item_t *item, int32_t x, zdwm_action_t *action) {
if (!(item->region.start <= x && item->region.end >= x)) return false;
if (!item->api.on_click) return true;
for (size_t i = 0; i < item->count; ++i) {
auto cell = &item->cells[i];
if (cell->region.start <= x && cell->region.end >= x) {
*action = item->api.on_click(item, i, x, item->state);
return true;
}
}
return true;
}
static inline bool
bar_side_click(bar_side_t *side, int32_t x, zdwm_action_t *action) {
if (side->region.start > x || side->region.end < x) return false;
for (size_t i = 0; i < side->count; ++i) {
if (bar_item_click(&side->items[i], x, action)) return true;
}
return true;
}
bool bar_click(
bar_t *bar,
zdwm_window_id_t window,
int32_t x,
zdwm_action_t *action
) {
for (size_t i = 0; i < bar->count; ++i) {
auto bar_output = &bar->bars[i];
if (bar_output->window_id != window) continue;
if (bar_side_click(&bar_output->left, x, action)) return true;
if (bar_item_click(&bar_output->center, x, action)) return true;
if (bar_side_click(&bar_output->right, x, action)) return true;
}
return false;
}

View File

@@ -3,6 +3,7 @@
#include <cairo.h>
#include <stddef.h>
#include <stdint.h>
#include <zdwm/action.h>
#include <zdwm/bar.h>
#include <zdwm/types.h>
@@ -42,3 +43,9 @@ void bar_init(bar_t *bar, listeners_t *listeners);
void bar_cleanup(bar_t *bar);
void bar_update(bar_t *bar);
bool bar_draw(bar_t *bar);
bool bar_click(
bar_t *bar,
zdwm_window_id_t window,
int32_t x,
zdwm_action_t *action
);

View File

@@ -371,7 +371,7 @@ static void toggle_bar_visibility(
command_buffer_push(command_buffer, &set_bar_visibility_command);
}
static void policy_resolve_action(
void policy_resolve_action(
const policy_context_t *ctx,
const zdwm_action_t *action,
command_buffer_t *out

View File

@@ -33,6 +33,12 @@ typedef struct policy_context_t {
const policy_bar_t bar;
} policy_context_t;
void policy_resolve_action(
const policy_context_t *ctx,
const zdwm_action_t *action,
command_buffer_t *out
);
/**
* @brief 事件路由:将运行时事件翻译为语义命令
*

View File

@@ -8,6 +8,7 @@
#include <sys/poll.h>
#include <sys/signalfd.h>
#include <unistd.h>
#include <zdwm/action.h>
#include <zdwm/layout.h>
#include "bar/bar.h"
@@ -456,10 +457,30 @@ static void runtime_scan(runtime_t *runtime) {
listeners_notify_initial_windows(&runtime->listeners, &runtime->state);
}
static bool runtime_handle_bar_click(
const policy_context_t *ctx,
const event_t *event,
bar_t *bar,
command_buffer_t *command_buffer
) {
if (event->type != ZDWM_EVENT_POINTER_BUTTON_PRESS) return false;
auto data = &event->as.pointer_button_press;
zdwm_action_t action = {.type = ZDWM_ACTION_NONE};
if (bar_click(bar, data->window, data->local.x, &action)) {
policy_resolve_action(ctx, &action, command_buffer);
return true;
}
return false;
}
static void runtime_handle_event(runtime_t *runtime, short int revents) {
auto backend = runtime->backend;
auto command_buffer = &runtime->command_buffer;
auto plan = &runtime->plan;
auto bar = &runtime->bar;
auto ctx = policy_context_init(runtime);
if (revents & POLLHUP) {
@@ -473,7 +494,10 @@ static void runtime_handle_event(runtime_t *runtime, short int revents) {
command_buffer_reset(command_buffer);
plan_reset(plan);
if (!runtime_handle_bar_click(&ctx, &event, bar, command_buffer)) {
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);