layers: add fully featured animations

Adds configs and layerrules to handle them

alas fixes #981

I have cooked
This commit is contained in:
Vaxry 2024-02-28 15:00:34 +00:00
parent f4f3aa2e50
commit 4bc669f933
9 changed files with 197 additions and 42 deletions

View file

@ -1480,7 +1480,7 @@ void CCompositor::cleanupFadingOut(const int& monid) {
if (ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) if (ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid)); g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid));
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) { if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) {
for (auto& m : m_vMonitors) { for (auto& m : m_vMonitors) {
for (auto& lsl : m->m_aLayerSurfaceLayers) { for (auto& lsl : m->m_aLayerSurfaceLayers) {
if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; }) != lsl.end()) { if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; }) != lsl.end()) {

View file

@ -617,6 +617,7 @@ void CConfigManager::setDefaultAnimationVars() {
if (isFirstLaunch) { if (isFirstLaunch) {
INITANIMCFG("global"); INITANIMCFG("global");
INITANIMCFG("windows"); INITANIMCFG("windows");
INITANIMCFG("layers");
INITANIMCFG("fade"); INITANIMCFG("fade");
INITANIMCFG("border"); INITANIMCFG("border");
INITANIMCFG("borderangle"); INITANIMCFG("borderangle");
@ -644,6 +645,7 @@ void CConfigManager::setDefaultAnimationVars() {
animationConfig["global"] = {false, "default", "", 8.f, 1, &animationConfig["general"], nullptr}; animationConfig["global"] = {false, "default", "", 8.f, 1, &animationConfig["general"], nullptr};
CREATEANIMCFG("windows", "global"); CREATEANIMCFG("windows", "global");
CREATEANIMCFG("layers", "global");
CREATEANIMCFG("fade", "global"); CREATEANIMCFG("fade", "global");
CREATEANIMCFG("border", "global"); CREATEANIMCFG("border", "global");
CREATEANIMCFG("borderangle", "global"); CREATEANIMCFG("borderangle", "global");
@ -658,6 +660,7 @@ void CConfigManager::setDefaultAnimationVars() {
CREATEANIMCFG("fadeSwitch", "fade"); CREATEANIMCFG("fadeSwitch", "fade");
CREATEANIMCFG("fadeShadow", "fade"); CREATEANIMCFG("fadeShadow", "fade");
CREATEANIMCFG("fadeDim", "fade"); CREATEANIMCFG("fadeDim", "fade");
CREATEANIMCFG("fadeLayers", "fade");
CREATEANIMCFG("specialWorkspace", "workspaces"); CREATEANIMCFG("specialWorkspace", "workspaces");
} }
@ -1840,7 +1843,7 @@ bool windowRuleValid(const std::string& RULE) {
} }
bool layerRuleValid(const std::string& RULE) { bool layerRuleValid(const std::string& RULE) {
return RULE == "noanim" || RULE == "blur" || RULE.starts_with("ignorealpha") || RULE.starts_with("ignorezero") || RULE.starts_with("xray"); return RULE == "noanim" || RULE == "blur" || RULE.starts_with("ignorealpha") || RULE.starts_with("ignorezero") || RULE.starts_with("xray") || RULE.starts_with("animation");
} }
std::optional<std::string> CConfigManager::handleWindowRule(const std::string& command, const std::string& value) { std::optional<std::string> CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {

View file

@ -113,9 +113,6 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive; layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive;
layersurface->surface = layersurface->layerSurface->surface; layersurface->surface = layersurface->layerSurface->surface;
// anim
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
// fix if it changed its mon // fix if it changed its mon
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output); const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
@ -166,8 +163,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL; const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
layersurface->alpha.setValue(0); layersurface->startAnimation(!(layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
layersurface->alpha = ((layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS) ? 0.f : 1.f);
layersurface->readyToDelete = false; layersurface->readyToDelete = false;
layersurface->fadingOut = false; layersurface->fadingOut = false;
@ -198,23 +194,17 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
layersurface->mapped = false; layersurface->mapped = false;
layersurface->fadingOut = true; layersurface->startAnimation(false);
layersurface->alpha.setValueAndWarp(0.f);
return; return;
} }
// anim
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut"));
// make a snapshot and start fade // make a snapshot and start fade
g_pHyprOpenGL->makeLayerSnapshot(layersurface); g_pHyprOpenGL->makeLayerSnapshot(layersurface);
layersurface->alpha = 0.f;
layersurface->startAnimation(false);
layersurface->mapped = false; layersurface->mapped = false;
layersurface->fadingOut = true;
g_pCompositor->addToFadingOutSafe(layersurface); g_pCompositor->addToFadingOutSafe(layersurface);
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output); const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);

View file

@ -3,9 +3,17 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
SLayerSurface::SLayerSurface() { SLayerSurface::SLayerSurface() {
alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_ENTIRE); alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeLayers"), nullptr, AVARDAMAGE_ENTIRE);
alpha.m_pLayer = this; realPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("layers"), nullptr, AVARDAMAGE_ENTIRE);
realSize.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("layers"), nullptr, AVARDAMAGE_ENTIRE);
alpha.m_pLayer = this;
realPosition.m_pLayer = this;
realSize.m_pLayer = this;
alpha.registerVar(); alpha.registerVar();
realPosition.registerVar();
realSize.registerVar();
alpha.setValueAndWarp(0.f);
} }
SLayerSurface::~SLayerSurface() { SLayerSurface::~SLayerSurface() {
@ -22,6 +30,7 @@ void SLayerSurface::applyRules() {
ignoreAlpha = false; ignoreAlpha = false;
ignoreAlphaValue = 0.f; ignoreAlphaValue = 0.f;
xray = -1; xray = -1;
animationStyle.reset();
for (auto& rule : g_pConfigManager->getMatchingRules(this)) { for (auto& rule : g_pConfigManager->getMatchingRules(this)) {
if (rule.rule == "noanim") if (rule.rule == "noanim")
@ -44,10 +53,120 @@ void SLayerSurface::applyRules() {
try { try {
xray = configStringToInt(vars[1]); xray = configStringToInt(vars[1]);
} catch (...) {} } catch (...) {}
} else if (rule.rule.starts_with("animation")) {
CVarList vars{rule.rule, 0, 's'};
animationStyle = vars[1];
} }
} }
} }
void SLayerSurface::startAnimation(bool in, bool instant) {
const auto ANIMSTYLE = animationStyle.value_or(realPosition.m_pConfig->pValues->internalStyle);
if (ANIMSTYLE == "slide") {
// get closest edge
const auto MIDDLE = geometry.middle();
const auto PMONITOR = g_pCompositor->getMonitorFromVector(MIDDLE);
const std::array<Vector2D, 4> edgePoints = {
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, 0},
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x / 2, PMONITOR->vecSize.y},
PMONITOR->vecPosition + Vector2D{0, PMONITOR->vecSize.y},
PMONITOR->vecPosition + Vector2D{PMONITOR->vecSize.x, PMONITOR->vecSize.y / 2},
};
float closest = std::numeric_limits<float>::max();
size_t leader = 0;
for (size_t i = 0; i < 4; ++i) {
float dist = MIDDLE.distance(edgePoints[i]);
if (dist < closest) {
leader = i;
closest = dist;
}
}
realSize.setValueAndWarp(geometry.size());
alpha.setValueAndWarp(1.f);
Vector2D prePos;
switch (leader) {
case 0:
// TOP
prePos = {geometry.x, PMONITOR->vecPosition.y - geometry.h};
break;
case 1:
// BOTTOM
prePos = {geometry.x, PMONITOR->vecPosition.y + PMONITOR->vecPosition.y};
break;
case 2:
// LEFT
prePos = {PMONITOR->vecPosition.x - geometry.w, geometry.y};
break;
case 3:
// RIGHT
prePos = {PMONITOR->vecPosition.x + PMONITOR->vecSize.x, geometry.y};
break;
default: UNREACHABLE();
}
if (in) {
realPosition.setValueAndWarp(prePos);
realPosition = geometry.pos();
} else {
realPosition.setValueAndWarp(geometry.pos());
realPosition = prePos;
}
} else if (ANIMSTYLE.starts_with("popin")) {
float minPerc = 0.f;
if (ANIMSTYLE.find("%") != std::string::npos) {
try {
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) {
; // oops
}
}
minPerc *= 0.01;
const auto GOALSIZE = (geometry.size() * minPerc).clamp({5, 5});
const auto GOALPOS = geometry.pos() + (geometry.size() - GOALSIZE) / 2.f;
alpha.setValueAndWarp(in ? 0.f : 1.f);
alpha = in ? 1.f : 0.f;
if (in) {
realSize.setValueAndWarp(GOALSIZE);
realPosition.setValueAndWarp(GOALPOS);
realSize = geometry.size();
realPosition = geometry.pos();
} else {
realSize.setValueAndWarp(geometry.size());
realPosition.setValueAndWarp(geometry.pos());
realSize = GOALSIZE;
realPosition = GOALPOS;
}
} else {
// fade
realPosition.setValueAndWarp(geometry.pos());
realSize.setValueAndWarp(geometry.size());
alpha = in ? 1.f : 0.f;
}
if (!in)
fadingOut = true;
}
bool SLayerSurface::isFadedOut() {
if (!fadingOut)
return false;
return !realPosition.isBeingAnimated() && !realSize.isBeingAnimated() && !alpha.isBeingAnimated();
}
CRegion SConstraint::getLogicCoordsRegion() { CRegion SConstraint::getLogicCoordsRegion() {
CRegion result; CRegion result;

View file

@ -19,6 +19,11 @@ struct SLayerSurface {
~SLayerSurface(); ~SLayerSurface();
void applyRules(); void applyRules();
void startAnimation(bool in, bool instant = false);
bool isFadedOut();
CAnimatedVariable realPosition;
CAnimatedVariable realSize;
wlr_layer_surface_v1* layerSurface; wlr_layer_surface_v1* layerSurface;
wl_list link; wl_list link;
@ -34,26 +39,28 @@ struct SLayerSurface {
DYNLISTENER(commitLayerSurface); DYNLISTENER(commitLayerSurface);
DYNLISTENER(newPopup); DYNLISTENER(newPopup);
CBox geometry = {0, 0, 0, 0}; CBox geometry = {0, 0, 0, 0};
Vector2D position; Vector2D position;
zwlr_layer_shell_v1_layer layer; zwlr_layer_shell_v1_layer layer;
bool mapped = false; bool mapped = false;
int monitorID = -1; int monitorID = -1;
std::string szNamespace = ""; std::string szNamespace = "";
CAnimatedVariable alpha; CAnimatedVariable alpha;
bool fadingOut = false; bool fadingOut = false;
bool readyToDelete = false; bool readyToDelete = false;
bool noProcess = false; bool noProcess = false;
bool noAnimations = false; bool noAnimations = false;
bool forceBlur = false; bool forceBlur = false;
int xray = -1; int xray = -1;
bool ignoreAlpha = false; bool ignoreAlpha = false;
float ignoreAlphaValue = 0.f; float ignoreAlphaValue = 0.f;
std::optional<std::string> animationStyle;
// For the list lookup // For the list lookup
bool operator==(const SLayerSurface& rhs) const { bool operator==(const SLayerSurface& rhs) const {

View file

@ -101,7 +101,7 @@ void CAnimationManager::tick() {
g_pHyprRenderer->damageWindow(w.get()); g_pHyprRenderer->damageWindow(w.get());
} }
} else if (PLAYER) { } else if (PLAYER) {
WLRBOXPREV = PLAYER->geometry; WLRBOXPREV = CBox{PLAYER->realPosition.vec(), PLAYER->realSize.vec()};
PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f); PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f);
if (!PMONITOR) if (!PMONITOR)
continue; continue;
@ -513,6 +513,27 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
if (style == "loop" || style == "once") if (style == "loop" || style == "once")
return ""; return "";
return "unknown style"; return "unknown style";
} else if (config.starts_with("layers")) {
if (style == "fade" || style == "" || style == "slide")
return "";
else if (style.starts_with("popin")) {
// try parsing
float minPerc = 0.f;
if (style.find("%") != std::string::npos) {
try {
auto percstr = style.substr(style.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) { return "invalid minperc"; }
return "";
}
minPerc; // fix warning
return "";
}
return "";
return "unknown style";
} else { } else {
return "animation has no styles"; return "animation has no styles";
} }

View file

@ -1812,13 +1812,22 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID); const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID);
CBox monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; CBox layerBox;
// some mafs to figure out the correct box
// the originalClosedPos is relative to the monitor's pos
Vector2D scaleXY = Vector2D((PMONITOR->scale * PLAYER->realSize.vec().x / (PLAYER->geometry.w * PMONITOR->scale)),
(PMONITOR->scale * PLAYER->realSize.vec().y / (PLAYER->geometry.h * PMONITOR->scale)));
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; layerBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x;
layerBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y;
layerBox.x = ((PLAYER->realPosition.vec().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - (((PLAYER->geometry.x - PMONITOR->vecPosition.x) * PMONITOR->scale) * scaleXY.x);
layerBox.y = ((PLAYER->realPosition.vec().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - (((PLAYER->geometry.y - PMONITOR->vecPosition.y) * PMONITOR->scale) * scaleXY.y);
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
m_bEndFrame = true; m_bEndFrame = true;
renderTextureInternalWithDamage(it->second.m_cTex, &monbox, PLAYER->alpha.fl(), &fakeDamage, 0); renderTextureInternalWithDamage(it->second.m_cTex, &layerBox, PLAYER->alpha.fl(), &fakeDamage, 0);
m_bEndFrame = false; m_bEndFrame = false;
} }

View file

@ -112,7 +112,7 @@ struct SCurrentRenderData {
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
CBox clipBox = {}; CBox clipBox = {}; // scaled coordinates
uint32_t discardMode = DISCARD_OPAQUE; uint32_t discardMode = DISCARD_OPAQUE;
float discardOpacity = 0.f; float discardOpacity = 0.f;

View file

@ -606,15 +606,20 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times
TRACY_GPU_ZONE("RenderLayer"); TRACY_GPU_ZONE("RenderLayer");
SRenderData renderdata = {pMonitor, time, pLayer->geometry.x, pLayer->geometry.y}; const auto REALPOS = pLayer->realPosition.vec();
const auto REALSIZ = pLayer->realSize.vec();
SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y};
renderdata.fadeAlpha = pLayer->alpha.fl(); renderdata.fadeAlpha = pLayer->alpha.fl();
renderdata.blur = pLayer->forceBlur; renderdata.blur = pLayer->forceBlur;
renderdata.surface = pLayer->layerSurface->surface; renderdata.surface = pLayer->layerSurface->surface;
renderdata.decorate = false; renderdata.decorate = false;
renderdata.w = pLayer->geometry.width; renderdata.w = REALSIZ.x;
renderdata.h = pLayer->geometry.height; renderdata.h = REALSIZ.y;
renderdata.blockBlurOptimization = pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM || pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; renderdata.blockBlurOptimization = pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM || pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND;
g_pHyprOpenGL->m_RenderData.clipBox = CBox{0, 0, pMonitor->vecSize.x, pMonitor->vecSize.y}.scale(pMonitor->scale);
g_pHyprOpenGL->m_pCurrentLayer = pLayer; g_pHyprOpenGL->m_pCurrentLayer = pLayer;
if (pLayer->ignoreAlpha) { if (pLayer->ignoreAlpha) {
@ -629,7 +634,8 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times
renderdata.popup = true; renderdata.popup = true;
wlr_layer_surface_v1_for_each_popup_surface(pLayer->layerSurface, renderSurface, &renderdata); wlr_layer_surface_v1_for_each_popup_surface(pLayer->layerSurface, renderSurface, &renderdata);
g_pHyprOpenGL->m_pCurrentLayer = nullptr; g_pHyprOpenGL->m_pCurrentLayer = nullptr;
g_pHyprOpenGL->m_RenderData.clipBox = {};
} }
void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) { void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) {