Skip to content

Commit

Permalink
Initial infrastructure for showing/hiding alert
Browse files Browse the repository at this point in the history
Use MainLoop to trigger alert from sources, manager receives and handles
visibility of alert panel.
  • Loading branch information
2hdddg committed Jan 27, 2024
1 parent 27153a9 commit 4043217
Show file tree
Hide file tree
Showing 15 changed files with 104 additions and 43 deletions.
13 changes: 12 additions & 1 deletion config/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ local function click_workspace(tag)
os.execute('swaymsg workspace "' .. tag .. '"')
end

local function render_alert()
return box(" ", RED);
end

local function render_time()
local t = os.time()
local markup = os.date("<span font='digital-7' size='40pt' color='" .. BLACK .. "' rise='-3pt'>%H:%M</span><span size='15pt' color='" .. BLACK .. "'>\n%Y-%m-%d</span>")
Expand Down Expand Up @@ -232,5 +236,12 @@ return {
sources = {
displays = {compositor = "sway"},
audio = {server = "pulseaudio"},
}
},
alert = {
anchor = "top",
widgets = {
{ padding = { top = 10 }, on_render = render_alert },
},
on_display = is_focused_display,
},
}
1 change: 1 addition & 0 deletions src/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ struct AudioConfig {
class Configuration {
public:
std::vector<PanelConfig> panels;
PanelConfig alertPanel;
DisplaysConfig displays;
AudioConfig audio;
int bufferWidth;
Expand Down
2 changes: 1 addition & 1 deletion src/DateTimeSources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ std::shared_ptr<TimeSource> TimeSource::Create(MainLoop& mainLoop,
}

auto source = std::shared_ptr<TimeSource>(new TimeSource(fd, dateSource));
mainLoop.Register(fd, "TimeSource", source);
mainLoop.RegisterIoHandler(fd, "TimeSource", source);
return source;
}

Expand Down
30 changes: 20 additions & 10 deletions src/MainLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ std::unique_ptr<MainLoop> MainLoop::Create() {

void MainLoop::Run() {
// Register internal events
m_polls.push_back(pollfd{.fd = m_eventFd, .events = POLLIN, .revents = 0});
m_polls.push_back(pollfd{.fd = m_wakeupFd, .events = POLLIN, .revents = 0});

do {
// Should be ppoll
Expand All @@ -36,11 +36,11 @@ void MainLoop::Run() {
if ((poll.events & poll.revents) != 0) {
// Special treatment on internal events. Empty events and
// rely on batch processing when all other events has been processed
if (poll.fd == m_eventFd) {
if (poll.fd == m_wakeupFd) {
uint64_t ignore;
spdlog::trace("Popping internal event");
m_wakupMutex.lock();
read(m_eventFd, &ignore, sizeof(uint64_t));
read(m_wakeupFd, &ignore, sizeof(uint64_t));
m_wakupMutex.unlock();
// For now internal events always means that a source is dirty
anyDirty = true;
Expand All @@ -52,28 +52,38 @@ void MainLoop::Run() {
}
}
}
if (anyDirty && m_batchHandler) {
m_batchHandler->OnBatchProcessed();
if (anyDirty && m_handler) {
m_handler->OnChanged();
}
if (m_alerted) {
m_handler->OnAlerted();
m_alerted = false;
}
} while (m_polls.size() > 0);
}

void MainLoop::Register(int fd, const std::string_view name, std::shared_ptr<IoHandler> ioHandler) {
void MainLoop::RegisterIoHandler(int fd, const std::string_view name,
std::shared_ptr<IoHandler> ioHandler) {
m_handlers[fd] = ioHandler;
m_polls.push_back(pollfd{.fd = fd, .events = POLLIN, .revents = 0});
spdlog::debug("Registering {} in main loop for fd {}", name, fd);
}

void MainLoop::RegisterBatchHandler(std::shared_ptr<IoBatchHandler> batchHandler) {
if (m_batchHandler) {
void MainLoop::RegisterNotificationHandler(std::shared_ptr<NotificationHandler> batchHandler) {
if (m_handler) {
spdlog::error("Only one batch handler supported");
}
m_batchHandler = batchHandler;
m_handler = batchHandler;
}

void MainLoop::Wakeup() {
m_wakupMutex.lock();
uint64_t inc = 1;
write(m_eventFd, &inc, sizeof(uint64_t));
write(m_wakeupFd, &inc, sizeof(uint64_t));
m_wakupMutex.unlock();
}

void MainLoop::AlertAndWakeup() {
m_alerted = true;
Wakeup();
}
24 changes: 15 additions & 9 deletions src/MainLoop.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <poll.h>

#include <atomic>
#include <functional>
#include <map>
#include <memory>
Expand All @@ -14,29 +15,34 @@ class IoHandler {
virtual bool OnRead() = 0;
};

class IoBatchHandler {
class NotificationHandler {
public:
virtual void OnBatchProcessed() = 0;
virtual void OnChanged() = 0;
virtual void OnAlerted() = 0;
};

class MainLoop {
public:
static std::unique_ptr<MainLoop> Create();

void Run();
void Register(int fd, const std::string_view name, std::shared_ptr<IoHandler> ioHandler);
void RegisterBatchHandler(std::shared_ptr<IoBatchHandler> ioBatchHandler);
void RegisterIoHandler(int fd, const std::string_view name,
std::shared_ptr<IoHandler> ioHandler);
void RegisterNotificationHandler(std::shared_ptr<NotificationHandler> ioBatchHandler);
// In cases where polling for events is done on another thread that thread should
// call this to trigger dirty check on all registered batch handlers.
// Or in cases where source gets dirty due to some other type of event
// call this to trigger dirty check on all registered io handlers.
// Or in cases where source gets dirty due to some other type of event than io.
void Wakeup();

void AlertAndWakeup();

private:
MainLoop(int eventFd) : m_eventFd(eventFd) {}
MainLoop(int eventFd) : m_wakeupFd(eventFd) {}

int m_eventFd;
int m_wakeupFd;
std::mutex m_wakupMutex;
std::atomic<bool> m_alerted;
std::vector<pollfd> m_polls;
std::map<int, std::shared_ptr<IoHandler>> m_handlers;
std::shared_ptr<IoBatchHandler> m_batchHandler;
std::shared_ptr<NotificationHandler> m_handler;
};
25 changes: 15 additions & 10 deletions src/Manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,38 @@ void Manager::WheelSurface(wl_surface* surface, int x, int y, int value) {
m_registry->BorrowOutputs().WheelSurface(surface, x, y, value);
}

void Manager::OnBatchProcessed() {
// Always publish sources
void Manager::OnChanged() {
m_sources->PublishAll();
// No need to redraw when not visible and not in transition
if (!m_visibilityChanged && !m_isVisible) return;
spdlog::debug("Processing batch of dirty sources");
if (m_visibilityChanged) {
m_visibilityChanged = false;
if (m_isVisible) {
m_sources->ForceRedraw();
if (m_alerted) {
m_registry->BorrowOutputs().HideAlert(*m_registry);
m_alerted = false;
}
} else {
m_registry->BorrowOutputs().Hide(*m_registry);
return;
}
}
m_registry->BorrowOutputs().Draw(*m_registry, *m_sources);
m_sources->SetAllDrawn();
if (m_isVisible) {
m_registry->BorrowOutputs().Draw(*m_registry, *m_sources);
m_sources->SetAllDrawn();
} else if (m_alerted) {
m_registry->BorrowOutputs().DrawAlert(*m_registry);
}
}

void Manager::OnAlerted() {}

void Manager::Hide() {
m_isVisible = false;
m_visibilityChanged = true;
OnBatchProcessed();
OnChanged();
}

void Manager::Show() {
m_isVisible = true;
m_visibilityChanged = true;
OnBatchProcessed();
OnChanged();
}
10 changes: 7 additions & 3 deletions src/Manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
#include "src/ScriptContext.h"
#include "src/Sources.h"

class Manager : public IoBatchHandler {
class Manager : public NotificationHandler {
public:
static std::shared_ptr<Manager> Create(std::shared_ptr<Registry> registry);
void SetSources(std::unique_ptr<Sources> sources) { m_sources = std::move(sources); }
virtual ~Manager() {}
// When a batch of IO events has been processed and sources needs to be published and/or needs
// to redrawn
void OnBatchProcessed() override;
void OnChanged() override;

void OnAlerted() override;

// Compositors tells manager when the overlays should be visible
void Show();
Expand All @@ -22,10 +24,12 @@ class Manager : public IoBatchHandler {
void WheelSurface(wl_surface* surface, int x, int y, int value);

private:
Manager(std::shared_ptr<Registry> registry) : m_registry(registry) {}
Manager(std::shared_ptr<Registry> registry)
: m_registry(registry), m_isVisible(false), m_visibilityChanged(false), m_alerted(false) {}

std::shared_ptr<Registry> m_registry;
bool m_isVisible;
bool m_visibilityChanged;
std::unique_ptr<Sources> m_sources;
bool m_alerted;
};
2 changes: 1 addition & 1 deletion src/NetworkSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ std::shared_ptr<NetworkSource> NetworkSource::Create(MainLoop &mainLoop) {
return nullptr;
}
auto source = std::shared_ptr<NetworkSource>(new NetworkSource(sock, fd));
mainLoop.Register(fd, "NetworkSource", source);
mainLoop.RegisterIoHandler(fd, "NetworkSource", source);
return source;
}

Expand Down
18 changes: 16 additions & 2 deletions src/Output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ void Outputs::Draw(const Registry &registry, const Sources &sources) {
}
// This panel is dirty, redraw it on every output
if (dirty) {
for (const auto &keyValue : m_map) {
keyValue.second->Draw(registry, panelConfig, *m_bufferPool);
for (const auto &nameAndOutput : m_map) {
nameAndOutput.second->Draw(registry, panelConfig, *m_bufferPool);
}
}
}
Expand All @@ -163,6 +163,20 @@ void Outputs::Hide(const Registry &registry) {
}
}

void Outputs::DrawAlert(const Registry &registry) {
spdlog::info("Draw alert");
for (const auto &nameAndOutput : m_map) {
nameAndOutput.second->Draw(registry, m_config->alertPanel, *m_bufferPool);
}
}

void Outputs::HideAlert(const Registry &registry) {
spdlog::info("Hide alert");
for (const auto &nameAndOutput : m_map) {
nameAndOutput.second->Hide(registry);
}
}

void Outputs::ClickSurface(wl_surface *surface, int x, int y) {
for (auto &kv : m_map) {
if (kv.second->ClickSurface(surface, x, y)) {
Expand Down
2 changes: 2 additions & 0 deletions src/Output.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class Outputs {

void Draw(const Registry& registry, const Sources& sources);
void Hide(const Registry& registry);
void DrawAlert(const Registry& registry);
void HideAlert(const Registry& registry);

void ClickSurface(wl_surface* surface, int x, int y);
void WheelSurface(wl_surface* surface, int x, int y, int value);
Expand Down
2 changes: 1 addition & 1 deletion src/PowerSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ std::shared_ptr<PowerSource> PowerSource::Create(MainLoop& mainLoop) {
return nullptr;
}
auto source = std::shared_ptr<PowerSource>(new PowerSource(fd));
mainLoop.Register(fd, "PowerSource", source);
mainLoop.RegisterIoHandler(fd, "PowerSource", source);
return source;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ std::shared_ptr<Registry> Registry::Create(std::shared_ptr<MainLoop> mainLoop,
// Two roundtrips, first to trigger registration, second to process binding requests.
if (wl_display_roundtrip(display) < 0 || wl_display_roundtrip(display) < 0) return nullptr;
// Register in mainloop
mainLoop->Register(wl_display_get_fd(display), "wayland", registry);
mainLoop->RegisterIoHandler(wl_display_get_fd(display), "wayland", registry);
// Initialize buffers in outputs
if (!registry->m_outputs->InitializeBuffers(*registry->m_shm)) {
spdlog::error("Failed to initialize output buffers");
Expand Down
8 changes: 8 additions & 0 deletions src/ScriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,14 @@ static std::shared_ptr<Configuration> ParseConfig(sol::optional<sol::table> root
auto panel = ParsePanelConfig(*panelTable, i);
config->panels.push_back(panel);
}
// Alert panel. Reserve index -1 for alert
std::optional<sol::table> alertPanelTable = (*root)["alert"];
if (alertPanelTable) {
config->alertPanel = ParsePanelConfig(*alertPanelTable, -1);
} else {
config->alertPanel = PanelConfig{.index = -1};
}

// Buffers
sol::optional<sol::table> buffersTable = (*root)["buffers"];
config->numBuffers = 1;
Expand Down
6 changes: 3 additions & 3 deletions src/SwayCompositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ static std::optional<Displays> ParseTree(const std::string &payload) {
std::shared_ptr<SwayCompositor> SwayCompositor::Connect(MainLoop &mainLoop, Visibility visibility) {
auto path = getenv("SWAYSOCK");
if (path == nullptr) {
spdlog::error("SWAYSOCK not set");
return nullptr;
spdlog::error("SWAYSOCK not set");
return nullptr;
}
spdlog::debug("Connecting to sway at {}", path);
auto fd = socket(AF_UNIX, SOCK_STREAM, 0);
Expand All @@ -215,7 +215,7 @@ std::shared_ptr<SwayCompositor> SwayCompositor::Connect(MainLoop &mainLoop, Visi
return nullptr;
}
auto t = std::shared_ptr<SwayCompositor>(new SwayCompositor(fd, visibility));
mainLoop.Register(fd, "Sway", t);
mainLoop.RegisterIoHandler(fd, "Sway", t);
t->Initialize();
return t;
}
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ int main(int argc, char* argv[]) {
// Let over control to mainloop and manager
manager->SetSources(std::move(sources));
sources = nullptr;
mainLoop->RegisterBatchHandler(manager);
mainLoop->RegisterNotificationHandler(manager);
mainLoop->Run();
return 0;
}

0 comments on commit 4043217

Please sign in to comment.