config/ui: add random-shuffle slideshow order (#352)

* feat: Add random-shuffle wallpaper order

Add a 'wallpaper#order' value, 'random-shuffle', that reshuffles when the
slideshow wraps so each cycle shows every image once in a new order.
This commit is contained in:
Robin Lind 2026-03-17 17:45:10 +01:00 committed by GitHub
parent 51e497dc6d
commit 0ca403a91e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 22 additions and 10 deletions

View file

@ -203,19 +203,19 @@ std::vector<CConfigManager::SSetting> CConfigManager::getSettings() {
auto resolvedPaths = RESOLVE_PATH.value();
if (resolvedPaths.size() > 1) {
if (order != "default" && order != "random") {
if (order != "default" && order != "random" && order != "random-shuffle") {
g_logger->log(LOG_WARN, "Invalid order value '{}', falling back to default", order);
order = "default";
}
if (order == "random") {
if (order == "random" || order == "random-shuffle") {
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(resolvedPaths.begin(), resolvedPaths.end(), g);
}
}
result.emplace_back(SSetting{.monitor = std::move(monitor), .fitMode = std::move(fitMode), .paths = std::move(resolvedPaths), .timeout = timeout});
result.emplace_back(SSetting{.monitor = std::move(monitor), .fitMode = std::move(fitMode), .paths = std::move(resolvedPaths), .order = std::move(order), .timeout = timeout});
}
return result;

View file

@ -16,6 +16,7 @@ class CConfigManager {
struct SSetting {
std::string monitor, fitMode;
std::vector<std::string> paths;
std::string order = "default";
int timeout = 0;
uint32_t id = 0;
};

View file

@ -6,6 +6,8 @@
#include "../ipc/IPC.hpp"
#include "../config/WallpaperMatcher.hpp"
#include <algorithm>
#include <random>
#include <hyprtoolkit/core/Output.hpp>
#include <hyprutils/string/String.hpp>
@ -24,14 +26,23 @@ static std::string_view pruneDesc(const std::string_view& sv) {
class CWallpaperTarget::CImagesData {
public:
CImagesData(Hyprtoolkit::eImageFitMode fitMode, const std::vector<std::string>& images, const int timeout = 0) :
fitMode(fitMode), images(images), timeout(timeout > 0 ? timeout : 30) {}
CImagesData(Hyprtoolkit::eImageFitMode fitMode, std::vector<std::string> images, const int timeout = 0, std::string order = "default") :
fitMode(fitMode), images(std::move(images)), order(std::move(order)), timeout(timeout > 0 ? timeout : 30) {}
const Hyprtoolkit::eImageFitMode fitMode;
const std::vector<std::string> images;
std::vector<std::string> images;
const std::string order;
const int timeout;
std::string nextImage() {
if (order == "random-shuffle" && current + 1 >= images.size()) {
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(images.begin(), images.end(), g);
current = 0;
return images[current];
}
current = (current + 1) % images.size();
return images[current];
}
@ -41,7 +52,7 @@ class CWallpaperTarget::CImagesData {
};
CWallpaperTarget::CWallpaperTarget(SP<Hyprtoolkit::IBackend> backend, SP<Hyprtoolkit::IOutput> output, const std::vector<std::string>& path, Hyprtoolkit::eImageFitMode fitMode,
const int timeout) : m_monitorName(output->port()), m_backend(backend) {
const int timeout, const std::string& order) : m_monitorName(output->port()), m_backend(backend) {
static const auto SPLASH_REPLY = HyprlandSocket::getFromSocket("/splash");
static const auto PENABLESPLASH = Hyprlang::CSimpleConfigValue<Hyprlang::INT>(g_config->hyprlang(), "splash");
@ -79,7 +90,7 @@ CWallpaperTarget::CWallpaperTarget(SP<Hyprtoolkit::IBackend> backend, SP<Hyprtoo
m_image->setPositionFlag(Hyprtoolkit::IElement::HT_POSITION_FLAG_CENTER, true);
if (path.size() > 1) {
m_imagesData = makeUnique<CImagesData>(fitMode, path, timeout);
m_imagesData = makeUnique<CImagesData>(fitMode, std::vector<std::string>(path), timeout, order);
m_timer =
m_backend->addTimer(std::chrono::milliseconds(std::chrono::seconds(m_imagesData->timeout)), [this](ASP<Hyprtoolkit::CTimer> self, void*) { onRepeatTimer(); }, nullptr);
}
@ -228,7 +239,7 @@ void CUI::targetChanged(const SP<Hyprtoolkit::IOutput>& mon) {
std::erase_if(m_targets, [&mon](const auto& e) { return e->m_monitorName == mon->port(); });
m_targets.emplace_back(makeShared<CWallpaperTarget>(m_backend, mon, TARGET->get().paths, toFitMode(TARGET->get().fitMode), TARGET->get().timeout));
m_targets.emplace_back(makeShared<CWallpaperTarget>(m_backend, mon, TARGET->get().paths, toFitMode(TARGET->get().fitMode), TARGET->get().timeout, TARGET->get().order));
}
const std::vector<SP<CWallpaperTarget>>& CUI::targets() {

View file

@ -17,7 +17,7 @@
class CWallpaperTarget {
public:
CWallpaperTarget(SP<Hyprtoolkit::IBackend> backend, SP<Hyprtoolkit::IOutput> output, const std::vector<std::string>& path,
Hyprtoolkit::eImageFitMode fitMode = Hyprtoolkit::IMAGE_FIT_MODE_COVER, const int timeout = 0);
Hyprtoolkit::eImageFitMode fitMode = Hyprtoolkit::IMAGE_FIT_MODE_COVER, const int timeout = 0, const std::string& order = "default");
~CWallpaperTarget();
CWallpaperTarget(const CWallpaperTarget&) = delete;