mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
feat(time): add TimeService for periodic widget updates
This commit is contained in:
+23
-10
@@ -26,6 +26,8 @@ constexpr float kBarPaddingX = 16.0f;
|
||||
Bar::Bar() = default;
|
||||
|
||||
bool Bar::initialize(TimeService* timeService) {
|
||||
m_time = timeService;
|
||||
|
||||
if (!m_wayland.connect()) {
|
||||
return false;
|
||||
}
|
||||
@@ -34,23 +36,30 @@ bool Bar::initialize(TimeService* timeService) {
|
||||
syncInstances();
|
||||
});
|
||||
|
||||
auto refreshAll = [this]() {
|
||||
m_wayland.setWorkspaceChangeCallback([this]() {
|
||||
for (auto& inst : m_instances) {
|
||||
if (inst->surface == nullptr || inst->surface->renderer() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
inst->surface->renderer()->makeCurrent();
|
||||
updateWidgets(*inst);
|
||||
if (inst->sceneRoot != nullptr && inst->sceneRoot->dirty()) {
|
||||
inst->surface->requestRedraw();
|
||||
}
|
||||
inst->surface->renderNow();
|
||||
}
|
||||
};
|
||||
|
||||
m_wayland.setWorkspaceChangeCallback(refreshAll);
|
||||
});
|
||||
|
||||
if (timeService != nullptr) {
|
||||
timeService->setTickCallback(refreshAll);
|
||||
timeService->setTickCallback([this]() {
|
||||
for (auto& inst : m_instances) {
|
||||
if (inst->surface == nullptr || inst->surface->renderer() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
inst->surface->renderer()->makeCurrent();
|
||||
updateWidgets(*inst);
|
||||
if (inst->sceneRoot != nullptr && inst->sceneRoot->dirty()) {
|
||||
inst->surface->requestRedraw();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
syncInstances();
|
||||
@@ -164,11 +173,15 @@ void Bar::destroyInstance(std::uint32_t outputName) {
|
||||
}
|
||||
|
||||
void Bar::populateWidgets(BarInstance& instance) {
|
||||
instance.startWidgets.push_back(std::make_unique<ClockWidget>());
|
||||
if (m_time != nullptr) {
|
||||
instance.startWidgets.push_back(std::make_unique<ClockWidget>(*m_time));
|
||||
}
|
||||
|
||||
instance.centerWidgets.push_back(std::make_unique<WorkspacesWidget>(m_wayland, instance.output));
|
||||
|
||||
instance.endWidgets.push_back(std::make_unique<ClockWidget>());
|
||||
if (m_time != nullptr) {
|
||||
instance.endWidgets.push_back(std::make_unique<ClockWidget>(*m_time));
|
||||
}
|
||||
}
|
||||
|
||||
void Bar::buildScene(BarInstance& instance, std::uint32_t width, std::uint32_t height) {
|
||||
|
||||
@@ -30,5 +30,6 @@ private:
|
||||
void updateWidgets(BarInstance& instance);
|
||||
|
||||
WaylandConnection m_wayland;
|
||||
TimeService* m_time = nullptr;
|
||||
std::vector<std::unique_ptr<BarInstance>> m_instances;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "time/TimeService.hpp"
|
||||
|
||||
#include <format>
|
||||
|
||||
void TimeService::setTickCallback(TickCallback callback) {
|
||||
m_callback = std::move(callback);
|
||||
}
|
||||
@@ -18,8 +20,15 @@ void TimeService::tick() {
|
||||
|
||||
if (sec != m_lastSecond) {
|
||||
m_lastSecond = sec;
|
||||
m_now = now;
|
||||
if (m_callback) {
|
||||
m_callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string TimeService::format(const char* fmt) const {
|
||||
const auto truncated = std::chrono::floor<std::chrono::seconds>(m_now);
|
||||
const auto local = std::chrono::current_zone()->to_local(truncated);
|
||||
return std::vformat(fmt, std::make_format_args(local));
|
||||
}
|
||||
|
||||
@@ -3,16 +3,23 @@
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
class TimeService {
|
||||
public:
|
||||
using Clock = std::chrono::system_clock;
|
||||
using TimePoint = Clock::time_point;
|
||||
using TickCallback = std::function<void()>;
|
||||
|
||||
void setTickCallback(TickCallback callback);
|
||||
[[nodiscard]] int pollTimeoutMs() const;
|
||||
void tick();
|
||||
|
||||
[[nodiscard]] TimePoint now() const noexcept { return m_now; }
|
||||
[[nodiscard]] std::string format(const char* fmt) const;
|
||||
|
||||
private:
|
||||
TickCallback m_callback;
|
||||
TimePoint m_now{};
|
||||
std::int64_t m_lastSecond = -1;
|
||||
};
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
#include "render/Palette.hpp"
|
||||
#include "render/Renderer.hpp"
|
||||
#include "time/TimeService.hpp"
|
||||
#include "ui/controls/Label.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <format>
|
||||
ClockWidget::ClockWidget(const TimeService& timeService)
|
||||
: m_time(timeService) {}
|
||||
|
||||
void ClockWidget::create(Renderer& renderer) {
|
||||
auto label = std::make_unique<Label>();
|
||||
@@ -21,9 +22,7 @@ void ClockWidget::layout(Renderer& renderer, float /*barWidth*/, float /*barHeig
|
||||
}
|
||||
|
||||
void ClockWidget::update(Renderer& renderer) {
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto local = std::chrono::current_zone()->to_local(now);
|
||||
auto text = std::format("{:%H:%M}", local);
|
||||
auto text = m_time.format("{:%H:%M:%S}");
|
||||
|
||||
if (text != m_lastText) {
|
||||
m_lastText = std::move(text);
|
||||
|
||||
@@ -2,15 +2,21 @@
|
||||
|
||||
#include "ui/Widget.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
class Label;
|
||||
class TimeService;
|
||||
|
||||
class ClockWidget : public Widget {
|
||||
public:
|
||||
explicit ClockWidget(const TimeService& timeService);
|
||||
|
||||
void create(Renderer& renderer) override;
|
||||
void layout(Renderer& renderer, float barWidth, float barHeight) override;
|
||||
void update(Renderer& renderer) override;
|
||||
|
||||
private:
|
||||
const TimeService& m_time;
|
||||
Label* m_label = nullptr;
|
||||
std::string m_lastText;
|
||||
};
|
||||
|
||||
@@ -112,6 +112,12 @@ void Surface::requestRedraw() {
|
||||
}
|
||||
}
|
||||
|
||||
void Surface::renderNow() {
|
||||
if (m_running && m_configured) {
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
Renderer* Surface::renderer() const noexcept {
|
||||
return m_renderer.get();
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
void setConfigureCallback(ConfigureCallback callback);
|
||||
void setUpdateCallback(UpdateCallback callback);
|
||||
void requestRedraw();
|
||||
void renderNow();
|
||||
void setAnimationManager(AnimationManager* manager) noexcept { m_animationManager = manager; }
|
||||
void setSceneRoot(Node* root) noexcept { m_sceneRoot = root; }
|
||||
[[nodiscard]] Renderer* renderer() const noexcept;
|
||||
|
||||
@@ -446,6 +446,9 @@ void WaylandConnection::onWorkspaceStateChanged(ext_workspace_handle_v1* workspa
|
||||
const std::string label = it->second.name.empty() ? "(unnamed)" : it->second.name;
|
||||
logInfo("workspace active: {}", label);
|
||||
}
|
||||
if (m_workspaceChangeCallback) {
|
||||
m_workspaceChangeCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user