From ac651802038a5d96ebe91fcd709752ddb787c75b Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Tue, 16 Jun 2026 00:31:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(bar):=20=E6=8C=89=E9=97=B4=E9=9A=94?= =?UTF-8?q?=E8=8A=82=E6=B5=81=20bar=5Fitem=20=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 base/time: time_monotonic_ms 与 time_create_monotonic_timerfd_by_fps - bar 初始化改用该工具创建 timerfd,移除内联的 itimerspec 拼装 - bar_item_update 按 update_interval_ms 节流,记录 last_updated_time 跳过过早更新 --- CMakeLists.txt | 1 + src/bar/bar.c | 30 ++++++++++---------------- src/bar/types.h | 1 + src/base/time.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ src/base/time.h | 6 ++++++ 5 files changed, 75 insertions(+), 19 deletions(-) create mode 100644 src/base/time.c create mode 100644 src/base/time.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 94e9d90..80842fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ add_executable(${APP_NAME} ${SOURCE_DIR}/base/color.c ${SOURCE_DIR}/base/log.c ${SOURCE_DIR}/base/process.c + ${SOURCE_DIR}/base/time.c ${SOURCE_DIR}/base/window_list.c ${SOURCE_DIR}/config/defaults.c diff --git a/src/bar/bar.c b/src/bar/bar.c index 1357e20..ef6fd24 100644 --- a/src/bar/bar.c +++ b/src/bar/bar.c @@ -1,12 +1,9 @@ #include "bar/bar.h" #include -#include -#include #include #include #include -#include #include #include #include @@ -18,6 +15,7 @@ #include "base/array.h" #include "base/macros.h" #include "base/memory.h" +#include "base/time.h" #include "core/listeners.h" static zdwm_bar_item_t *bar_add_item( @@ -91,21 +89,7 @@ void bar_init(bar_t *bar, listeners_t *listeners) { bar_output_add_workspace(bar_output, &bar->config, listeners); } - bar->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); - auto interval_ns = 1'000'000'000ULL / bar->config.fps; - - struct itimerspec timer_spec = { - .it_interval = - { - .tv_sec = interval_ns / 1'000'000'000, - .tv_nsec = interval_ns % 1'000'000'000, - }, - .it_value = { - .tv_sec = 0, - .tv_nsec = interval_ns % 1'000'000'000, - }, - }; - timerfd_settime(bar->timerfd, 0, &timer_spec, nullptr); + bar->timerfd = time_create_monotonic_timerfd_by_fps(bar->config.fps); } static void bar_side_cleanup(bar_side_t *side) { @@ -139,7 +123,15 @@ void bar_cleanup(bar_t *bar) { static inline void bar_item_update(zdwm_bar_item_t *item) { auto update = item->api.update; - if (update) update(item, &bar_cell_api, item->state); + if (!update) return; + + auto update_interval_ms = item->api.update_interval_ms; + auto last_updated_time = item->last_updated_time; + auto now = time_monotonic_ms(); + if (now < last_updated_time + update_interval_ms) return; + + item->last_updated_time = now; + update(item, &bar_cell_api, item->state); } static inline void bar_side_update(bar_side_t *side) { diff --git a/src/bar/types.h b/src/bar/types.h index 92375ce..9effc7c 100644 --- a/src/bar/types.h +++ b/src/bar/types.h @@ -32,6 +32,7 @@ struct zdwm_bar_item_t { void *state; zdwm_bar_item_type_t api; bool dirty; + uint64_t last_updated_time; }; typedef struct bar_side_t { diff --git a/src/base/time.c b/src/base/time.c new file mode 100644 index 0000000..283bb5a --- /dev/null +++ b/src/base/time.c @@ -0,0 +1,56 @@ +#include "base/time.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "base/log.h" + +static int time_create_monotonic_timerfd(const struct itimerspec *itimerspec) { + auto timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (timerfd == -1) { + auto err = errno; + warn("time_create_timerfd failed: %s", strerror(err)); + return timerfd; + } + + timerfd_settime(timerfd, 0, itimerspec, nullptr); + return timerfd; +} + +static constexpr auto NANOSECONDS_OF_ONE_SECOND = 1'000'000'000ULL; + +int time_create_monotonic_timerfd_by_fps(uint32_t fps) { + if (fps == 0) fps = 30; + + auto interval_ns = NANOSECONDS_OF_ONE_SECOND / fps; + + /* clang-format off */ + struct itimerspec timer_spec = { + .it_value = { + .tv_sec = 0, + .tv_nsec = interval_ns % NANOSECONDS_OF_ONE_SECOND, + }, + .it_interval = { + .tv_sec = interval_ns / NANOSECONDS_OF_ONE_SECOND, + .tv_nsec = interval_ns % NANOSECONDS_OF_ONE_SECOND, + }, + }; + /* clang-format on */ + + return time_create_monotonic_timerfd(&timer_spec); +} + +static uint64_t time_monotonic_ns(void) { + struct timespec timestamp = {0}; + if (clock_gettime(CLOCK_MONOTONIC, ×tamp) == -1) { + warn("clock_gettime failed: %s", strerror(errno)); + } + return timestamp.tv_sec * NANOSECONDS_OF_ONE_SECOND + timestamp.tv_nsec; +} + +uint64_t time_monotonic_ms(void) { return time_monotonic_ns() / 1'000'000U; } diff --git a/src/base/time.h b/src/base/time.h new file mode 100644 index 0000000..d615b8c --- /dev/null +++ b/src/base/time.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +int time_create_monotonic_timerfd_by_fps(uint32_t fps); +uint64_t time_monotonic_ms(void);