feat(bar): 按间隔节流 bar_item 更新
- 新增 base/time: time_monotonic_ms 与 time_create_monotonic_timerfd_by_fps - bar 初始化改用该工具创建 timerfd,移除内联的 itimerspec 拼装 - bar_item_update 按 update_interval_ms 节流,记录 last_updated_time 跳过过早更新
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#include "bar/bar.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <bits/time.h>
|
||||
#include <bits/types/struct_itimerspec.h>
|
||||
#include <cairo.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <unistd.h>
|
||||
#include <zdwm/bar.h>
|
||||
#include <zdwm/types.h>
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
56
src/base/time.c
Normal file
56
src/base/time.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "base/time.h"
|
||||
|
||||
#include <bits/time.h>
|
||||
#include <bits/types/struct_itimerspec.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <time.h>
|
||||
|
||||
#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; }
|
||||
6
src/base/time.h
Normal file
6
src/base/time.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int time_create_monotonic_timerfd_by_fps(uint32_t fps);
|
||||
uint64_t time_monotonic_ms(void);
|
||||
Reference in New Issue
Block a user