|
7 | 7 | #include "../config/WallpaperMatcher.hpp" |
8 | 8 |
|
9 | 9 | #include <algorithm> |
| 10 | +#include <fstream> |
10 | 11 | #include <random> |
11 | 12 | #include <hyprtoolkit/core/Output.hpp> |
12 | 13 |
|
@@ -143,6 +144,37 @@ void CWallpaperTarget::onRepeatTimer() { |
143 | 144 | IPC::g_IPCSocket->onWallpaperChanged(m_monitorName, m_lastPath); |
144 | 145 | } |
145 | 146 |
|
| 147 | +void CWallpaperTarget::transitionTo(const std::string& path, |
| 148 | + Hyprtoolkit::eImageFitMode fitMode, |
| 149 | + float duration, |
| 150 | + const std::string& shaderPath) { |
| 151 | + m_lastPath = path; |
| 152 | + |
| 153 | + std::string shaderSource; |
| 154 | + if (!shaderPath.empty()) { |
| 155 | + std::ifstream file(shaderPath); |
| 156 | + if (file.is_open()) |
| 157 | + shaderSource = std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); |
| 158 | + else |
| 159 | + g_logger->log(LOG_ERR, "Could not open transition shader: {}", shaderPath); |
| 160 | + } |
| 161 | + |
| 162 | + m_image->transitionTo(path, fitMode, duration, shaderSource); |
| 163 | +} |
| 164 | + |
| 165 | +void CWallpaperTarget::replaceImmediate(const std::string& path, |
| 166 | + Hyprtoolkit::eImageFitMode fitMode) { |
| 167 | + m_lastPath = path; |
| 168 | + |
| 169 | + m_image->rebuild() |
| 170 | + ->path(std::string{path}) |
| 171 | + ->size({Hyprtoolkit::CDynamicSize::HT_SIZE_PERCENT, |
| 172 | + Hyprtoolkit::CDynamicSize::HT_SIZE_PERCENT, {1.F, 1.F}}) |
| 173 | + ->sync(true) |
| 174 | + ->fitMode(fitMode) |
| 175 | + ->commence(); |
| 176 | +} |
| 177 | + |
146 | 178 | void CUI::registerOutput(const SP<Hyprtoolkit::IOutput>& mon) { |
147 | 179 | g_matcher->registerOutput(mon->port(), pruneDesc(mon->desc())); |
148 | 180 | if (IPC::g_IPCSocket) |
@@ -237,11 +269,37 @@ void CUI::targetChanged(const SP<Hyprtoolkit::IOutput>& mon) { |
237 | 269 | return; |
238 | 270 | } |
239 | 271 |
|
240 | | - std::erase_if(m_targets, [&mon](const auto& e) { return e->m_monitorName == mon->port(); }); |
241 | | - |
242 | | - m_targets.emplace_back(makeShared<CWallpaperTarget>(m_backend, mon, TARGET->get().paths, toFitMode(TARGET->get().fitMode), TARGET->get().timeout, TARGET->get().order)); |
| 272 | + auto existingTarget = findTarget(mon->port()); |
| 273 | + |
| 274 | + if (existingTarget) { |
| 275 | + auto outConfig = g_config->getAnimationConfig("fadeLayersOut"); |
| 276 | + auto inConfig = g_config->getAnimationConfig("fadeLayersIn"); |
| 277 | + |
| 278 | + if (inConfig.enabled || outConfig.enabled) { |
| 279 | + existingTarget->transitionTo( |
| 280 | + TARGET->get().paths.front(), |
| 281 | + toFitMode(TARGET->get().fitMode), |
| 282 | + std::max(outConfig.duration, inConfig.duration), |
| 283 | + TARGET->get().shaderPath); |
| 284 | + } else { |
| 285 | + // Animations disabled, swap without a transition. |
| 286 | + existingTarget->replaceImmediate( |
| 287 | + TARGET->get().paths.front(), |
| 288 | + toFitMode(TARGET->get().fitMode)); |
| 289 | + } |
| 290 | + } else { |
| 291 | + m_targets.emplace_back(makeShared<CWallpaperTarget>(m_backend, mon, TARGET->get().paths, toFitMode(TARGET->get().fitMode), TARGET->get().timeout, TARGET->get().order)); |
| 292 | + } |
243 | 293 | } |
244 | 294 |
|
245 | 295 | const std::vector<SP<CWallpaperTarget>>& CUI::targets() { |
246 | 296 | return m_targets; |
247 | 297 | } |
| 298 | + |
| 299 | +SP<CWallpaperTarget> CUI::findTarget(const std::string& monitorName) { |
| 300 | + for (const auto& target : m_targets) { |
| 301 | + if (target->m_monitorName == monitorName) |
| 302 | + return target; |
| 303 | + } |
| 304 | + return nullptr; |
| 305 | +} |
0 commit comments