mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-02 18:26:00 +01:00
layers: add fully featured animations
Adds configs and layerrules to handle them alas fixes #981 I have cooked
This commit is contained in:
parent
f4f3aa2e50
commit
4bc669f933
9 changed files with 197 additions and 42 deletions
|
@ -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)
|
||||
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& 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()) {
|
||||
|
|
|
@ -617,6 +617,7 @@ void CConfigManager::setDefaultAnimationVars() {
|
|||
if (isFirstLaunch) {
|
||||
INITANIMCFG("global");
|
||||
INITANIMCFG("windows");
|
||||
INITANIMCFG("layers");
|
||||
INITANIMCFG("fade");
|
||||
INITANIMCFG("border");
|
||||
INITANIMCFG("borderangle");
|
||||
|
@ -644,6 +645,7 @@ void CConfigManager::setDefaultAnimationVars() {
|
|||
animationConfig["global"] = {false, "default", "", 8.f, 1, &animationConfig["general"], nullptr};
|
||||
|
||||
CREATEANIMCFG("windows", "global");
|
||||
CREATEANIMCFG("layers", "global");
|
||||
CREATEANIMCFG("fade", "global");
|
||||
CREATEANIMCFG("border", "global");
|
||||
CREATEANIMCFG("borderangle", "global");
|
||||
|
@ -658,6 +660,7 @@ void CConfigManager::setDefaultAnimationVars() {
|
|||
CREATEANIMCFG("fadeSwitch", "fade");
|
||||
CREATEANIMCFG("fadeShadow", "fade");
|
||||
CREATEANIMCFG("fadeDim", "fade");
|
||||
CREATEANIMCFG("fadeLayers", "fade");
|
||||
|
||||
CREATEANIMCFG("specialWorkspace", "workspaces");
|
||||
}
|
||||
|
@ -1840,7 +1843,7 @@ bool windowRuleValid(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) {
|
||||
|
|
|
@ -113,9 +113,6 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
|||
layersurface->keyboardExclusive = layersurface->layerSurface->current.keyboard_interactive;
|
||||
layersurface->surface = layersurface->layerSurface->surface;
|
||||
|
||||
// anim
|
||||
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
|
||||
|
||||
// fix if it changed its mon
|
||||
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 bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
|
||||
layersurface->alpha.setValue(0);
|
||||
layersurface->alpha = ((layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS) ? 0.f : 1.f);
|
||||
layersurface->startAnimation(!(layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
|
||||
layersurface->readyToDelete = false;
|
||||
layersurface->fadingOut = false;
|
||||
|
||||
|
@ -198,23 +194,17 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
|||
|
||||
layersurface->mapped = false;
|
||||
|
||||
layersurface->fadingOut = true;
|
||||
|
||||
layersurface->alpha.setValueAndWarp(0.f);
|
||||
layersurface->startAnimation(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// anim
|
||||
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut"));
|
||||
|
||||
// make a snapshot and start fade
|
||||
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
||||
layersurface->alpha = 0.f;
|
||||
|
||||
layersurface->startAnimation(false);
|
||||
|
||||
layersurface->mapped = false;
|
||||
|
||||
layersurface->fadingOut = true;
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(layersurface);
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
||||
|
|
|
@ -3,9 +3,17 @@
|
|||
#include "../Compositor.hpp"
|
||||
|
||||
SLayerSurface::SLayerSurface() {
|
||||
alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_ENTIRE);
|
||||
alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeLayers"), nullptr, AVARDAMAGE_ENTIRE);
|
||||
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();
|
||||
realPosition.registerVar();
|
||||
realSize.registerVar();
|
||||
|
||||
alpha.setValueAndWarp(0.f);
|
||||
}
|
||||
|
||||
SLayerSurface::~SLayerSurface() {
|
||||
|
@ -22,6 +30,7 @@ void SLayerSurface::applyRules() {
|
|||
ignoreAlpha = false;
|
||||
ignoreAlphaValue = 0.f;
|
||||
xray = -1;
|
||||
animationStyle.reset();
|
||||
|
||||
for (auto& rule : g_pConfigManager->getMatchingRules(this)) {
|
||||
if (rule.rule == "noanim")
|
||||
|
@ -44,10 +53,120 @@ void SLayerSurface::applyRules() {
|
|||
try {
|
||||
xray = configStringToInt(vars[1]);
|
||||
} 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 result;
|
||||
|
||||
|
|
|
@ -19,6 +19,11 @@ struct SLayerSurface {
|
|||
~SLayerSurface();
|
||||
|
||||
void applyRules();
|
||||
void startAnimation(bool in, bool instant = false);
|
||||
bool isFadedOut();
|
||||
|
||||
CAnimatedVariable realPosition;
|
||||
CAnimatedVariable realSize;
|
||||
|
||||
wlr_layer_surface_v1* layerSurface;
|
||||
wl_list link;
|
||||
|
@ -55,6 +60,8 @@ struct SLayerSurface {
|
|||
bool ignoreAlpha = false;
|
||||
float ignoreAlphaValue = 0.f;
|
||||
|
||||
std::optional<std::string> animationStyle;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SLayerSurface& rhs) const {
|
||||
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
|
||||
|
|
|
@ -101,7 +101,7 @@ void CAnimationManager::tick() {
|
|||
g_pHyprRenderer->damageWindow(w.get());
|
||||
}
|
||||
} 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);
|
||||
if (!PMONITOR)
|
||||
continue;
|
||||
|
@ -513,6 +513,27 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
|
|||
if (style == "loop" || style == "once")
|
||||
return "";
|
||||
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 {
|
||||
return "animation has no styles";
|
||||
}
|
||||
|
|
|
@ -1812,13 +1812,22 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
|
|||
|
||||
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)));
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ struct SCurrentRenderData {
|
|||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
|
||||
CBox clipBox = {};
|
||||
CBox clipBox = {}; // scaled coordinates
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
|
|
@ -606,15 +606,20 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times
|
|||
|
||||
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.blur = pLayer->forceBlur;
|
||||
renderdata.surface = pLayer->layerSurface->surface;
|
||||
renderdata.decorate = false;
|
||||
renderdata.w = pLayer->geometry.width;
|
||||
renderdata.h = pLayer->geometry.height;
|
||||
renderdata.w = REALSIZ.x;
|
||||
renderdata.h = REALSIZ.y;
|
||||
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;
|
||||
|
||||
if (pLayer->ignoreAlpha) {
|
||||
|
@ -630,6 +635,7 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times
|
|||
wlr_layer_surface_v1_for_each_popup_surface(pLayer->layerSurface, renderSurface, &renderdata);
|
||||
|
||||
g_pHyprOpenGL->m_pCurrentLayer = nullptr;
|
||||
g_pHyprOpenGL->m_RenderData.clipBox = {};
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) {
|
||||
|
|
Loading…
Reference in a new issue