diff --git a/README.md b/README.md index 1c6fec6..207b29d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Hyprpaper is a blazing fast wallpaper utility for Hyprland with the ability to d # Features - Per-output wallpapers - - fill or contain modes + - fill, tile or contain modes - fractional scaling support - IPC for blazing fast wallpaper switches - preloading targets into memory @@ -91,7 +91,7 @@ splash = true Preload will tell Hyprland to load a particular image (supported formats: png, jpg, jpeg, webp). Wallpaper will apply the wallpaper to the selected output (`monitor` is the monitor's name, easily can be retrieved with `hyprctl monitors`. You can leave it empty to set all monitors without an active wallpaper. You can also use `desc:` followed by the monitor's description without the (PORT) at the end) -You may add `contain:` before the file path in `wallpaper=` to set the mode to contain instead of cover: +You may add `contain:` or `tile:` before the file path in `wallpaper=` to set the mode to either contain or tile, respectively, instead of cover: ``` wallpaper = monitor,contain:/path/to/image.jpg diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index 3500921..cfbdf50 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -515,6 +515,7 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { const auto PWALLPAPERTARGET = m_mMonitorActiveWallpaperTargets[pMonitor]; const auto CONTAIN = m_mMonitorWallpaperRenderData[pMonitor->name].contain; + const auto TILE = m_mMonitorWallpaperRenderData[pMonitor->name].tile; if (!PWALLPAPERTARGET) { Debug::log(CRIT, "wallpaper target null in render??"); @@ -567,8 +568,14 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { Debug::log(LOG, "Image data for %s: %s at [%.2f, %.2f], scale: %.2f (original image size: [%i, %i])", pMonitor->name.c_str(), PWALLPAPERTARGET->m_szPath.c_str(), origin.x, origin.y, scale, (int)PWALLPAPERTARGET->m_vSize.x, (int)PWALLPAPERTARGET->m_vSize.y); - cairo_scale(PCAIRO, scale, scale); - cairo_set_source_surface(PCAIRO, PWALLPAPERTARGET->m_pCairoSurface, origin.x, origin.y); + if (TILE) { + cairo_pattern_t* pattern = cairo_pattern_create_for_surface(PWALLPAPERTARGET->m_pCairoSurface); + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); + cairo_set_source(PCAIRO, pattern); + } else { + cairo_scale(PCAIRO, scale, scale); + cairo_set_source_surface(PCAIRO, PWALLPAPERTARGET->m_pCairoSurface, origin.x, origin.y); + } cairo_paint(PCAIRO); diff --git a/src/Hyprpaper.hpp b/src/Hyprpaper.hpp index 4ab3390..9327906 100644 --- a/src/Hyprpaper.hpp +++ b/src/Hyprpaper.hpp @@ -18,6 +18,7 @@ struct SWallpaperRenderData { bool contain = false; + bool tile = false; }; class CHyprpaper { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 212b6b2..6e6901a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -4,8 +4,8 @@ #include static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { - const std::string COMMAND = C; - const std::string VALUE = V; + const std::string COMMAND = C; + const std::string VALUE = V; Hyprlang::CParseResult result; if (VALUE.find_first_of(',') == std::string::npos) { @@ -23,6 +23,13 @@ static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { contain = true; } + bool tile = false; + + if (WALLPAPER.find("tile:") == 0) { + WALLPAPER = WALLPAPER.substr(5); + tile = true; + } + if (WALLPAPER[0] == '~') { static const char* const ENVHOME = getenv("HOME"); WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); @@ -44,6 +51,7 @@ static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { g_pHyprpaper->clearWallpaperFromMonitor(MONITOR); g_pHyprpaper->m_mMonitorActiveWallpapers[MONITOR] = WALLPAPER; g_pHyprpaper->m_mMonitorWallpaperRenderData[MONITOR].contain = contain; + g_pHyprpaper->m_mMonitorWallpaperRenderData[MONITOR].tile = tile; if (MONITOR.empty()) { for (auto& m : g_pHyprpaper->m_vMonitors) { @@ -51,6 +59,7 @@ static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { g_pHyprpaper->clearWallpaperFromMonitor(m->name); g_pHyprpaper->m_mMonitorActiveWallpapers[m->name] = WALLPAPER; g_pHyprpaper->m_mMonitorWallpaperRenderData[m->name].contain = contain; + g_pHyprpaper->m_mMonitorWallpaperRenderData[m->name].tile = tile; } } } else { @@ -141,6 +150,9 @@ static Hyprlang::CParseResult handleReload(const char* C, const char* V) { WALLPAPER = WALLPAPER.substr(8); } + if (WALLPAPER.find("tile:") == 0) + WALLPAPER = WALLPAPER.substr(5); + auto preloadResult = handlePreload(C, WALLPAPER.c_str()); if (preloadResult.error) return preloadResult; diff --git a/src/main.cpp b/src/main.cpp index d833364..d458797 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,4 +31,4 @@ int main(int argc, char** argv, char** envp) { g_pHyprpaper->init(); return 0; -} \ No newline at end of file +}