Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement workspace scale animations #7501

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -741,8 +741,6 @@ void CConfigManager::setDefaultAnimationVars() {
INITANIMCFG("fadeShadow");
INITANIMCFG("fadeDim");

// border

// workspaces
INITANIMCFG("workspaces");
INITANIMCFG("workspacesIn");
Expand Down Expand Up @@ -777,6 +775,12 @@ void CConfigManager::setDefaultAnimationVars() {
CREATEANIMCFG("fadeLayers", "fade");
CREATEANIMCFG("fadeLayersIn", "fadeLayers");
CREATEANIMCFG("fadeLayersOut", "fadeLayers");
CREATEANIMCFG("fadeWorkspaces", "fade");
CREATEANIMCFG("fadeWorkspacesIn", "fadeWorkspaces");
CREATEANIMCFG("fadeWorkspacesOut", "fadeWorkspaces");
CREATEANIMCFG("fadeSpecialWorkspace", "fadeWorkspaces");
CREATEANIMCFG("fadeSpecialWorkspaceIn", "fadeSpecialWorkspace");
CREATEANIMCFG("fadeSpecialWorkspaceOut", "fadeSpecialWorkspace");

CREATEANIMCFG("workspacesIn", "workspaces");
CREATEANIMCFG("workspacesOut", "workspaces");
Expand Down
132 changes: 59 additions & 73 deletions src/desktop/Workspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,18 @@ void CWorkspace::init(PHLWORKSPACE self) {
g_pConfigManager->getAnimationPropertyConfig("workspacesIn"),
self, AVARDAMAGE_ENTIRE);
m_fAlpha.create(AVARTYPE_FLOAT,
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self,
AVARDAMAGE_ENTIRE);
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("fadeSpecialWorkspaceIn") :
g_pConfigManager->getAnimationPropertyConfig("fadeWorkspacesIn"),
self, AVARDAMAGE_ENTIRE);
m_fAlpha.setValueAndWarp(1.f);
m_fScaleClients.create(
AVARTYPE_FLOAT, m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"),
self, AVARDAMAGE_ENTIRE);
m_fScaleClients.setValueAndWarp(1.f);

m_vRenderOffset.registerVar();
m_fAlpha.registerVar();
m_fScaleClients.registerVar();

const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(self);
if (RULEFORTHIS.defaultName.has_value())
Expand Down Expand Up @@ -83,13 +89,15 @@ CWorkspace::~CWorkspace() {

void CWorkspace::startAnim(bool in, bool left, bool instant) {
if (!instant) {
const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out");
const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out");
const std::string ANIMNAME2 = std::format("fade{}{}", m_bIsSpecialWorkspace ? "SpecialWorkspace" : "Workspaces", in ? "In" : "Out");

m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME2);
m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
m_fScaleClients.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
}

const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
const auto ANIMSTYLE = m_vRenderOffset.m_pConfig->pValues->internalStyle;
static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces");

// set floating windows offset callbacks
Expand All @@ -102,95 +110,73 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
};
});

if (ANIMSTYLE.starts_with("slidefade")) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
float movePerc = 100.f;
m_fAlpha.setValueAndWarp(in ? 0.F : 1.F);
m_fAlpha = in ? 1.F : 0.F;

// handle animation styles for the movement one
if (m_vRenderOffset.m_pConfig->pValues->internalEnabled) {
if (ANIMSTYLE.starts_with("slide") && ANIMSTYLE.contains("%")) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
float movePerc = 0.F;

if (ANIMSTYLE.find("%") != std::string::npos) {
try {
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ') + 1);
movePerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); }
}

m_fAlpha.setValueAndWarp(1.f);
m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
m_fScaleClients.setValueAndWarp(1.F);

if (ANIMSTYLE.starts_with("slidevert")) {
if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f)));
m_vRenderOffset = Vector2D(0, 0);
} else
m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f));

if (ANIMSTYLE.starts_with("slidefadevert")) {
if (in) {
m_fAlpha.setValueAndWarp(0.f);
m_vRenderOffset.setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f)));
m_fAlpha = 1.f;
m_vRenderOffset = Vector2D(0, 0);
} else {
m_fAlpha.setValueAndWarp(1.f);
m_fAlpha = 0.f;
m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f));
}
} else {
if (in) {
m_fAlpha.setValueAndWarp(0.f);
m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0));
m_fAlpha = 1.f;
m_vRenderOffset = Vector2D(0, 0);
} else {
m_fAlpha.setValueAndWarp(1.f);
m_fAlpha = 0.f;
m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0);
if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0));
m_vRenderOffset = Vector2D(0, 0);
} else
m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0);
}
}
} else if (ANIMSTYLE == "fade") {
m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade.
} else if (ANIMSTYLE.starts_with("popin")) {
m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));

if (in) {
m_fAlpha.setValueAndWarp(0.f);
m_fAlpha = 1.f;
} else {
m_fAlpha.setValueAndWarp(1.f);
m_fAlpha = 0.f;
}
} else if (ANIMSTYLE == "slidevert") {
// fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP;
float startPerc = 0.F;

m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
try {
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ') + 1);
startPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); }

if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE));
m_vRenderOffset = Vector2D(0, 0);
if (in) {
m_fScaleClients.setValueAndWarp(startPerc / 100.F);
m_fScaleClients = 1.F;
} else {
m_fScaleClients.setValueAndWarp(1.F);
m_fScaleClients = startPerc / 100.F;
}
} else {
m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE);
}
} else {
// fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP;

m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
// fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP;

if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0));
m_vRenderOffset = Vector2D(0, 0);
} else {
m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0);
}
}
m_fScaleClients.setValueAndWarp(1.F);

if (m_bIsSpecialWorkspace) {
// required for open/close animations
if (in) {
m_fAlpha.setValueAndWarp(0.f);
m_fAlpha = 1.f;
} else {
m_fAlpha.setValueAndWarp(1.f);
m_fAlpha = 0.f;
if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0));
m_vRenderOffset = Vector2D(0, 0);
} else
m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0);
}
}

if (instant) {
m_vRenderOffset.warp();
m_fAlpha.warp();
m_fScaleClients.warp();
}
}

Expand Down
1 change: 1 addition & 0 deletions src/desktop/Workspace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class CWorkspace {
// for animations
CAnimatedVariable<Vector2D> m_vRenderOffset;
CAnimatedVariable<float> m_fAlpha;
CAnimatedVariable<float> m_fScaleClients;
bool m_bForceRendering = false;

// allows damage to propagate.
Expand Down
4 changes: 2 additions & 2 deletions src/managers/AnimationManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,9 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,

return "unknown style";
} else if (config.starts_with("workspaces") || config.starts_with("specialWorkspace")) {
if (style == "slide" || style == "slidevert" || style == "fade")
if (style == "slide" || style == "slidevert")
return "";
else if (style.starts_with("slidefade")) {
else if (style.starts_with("slide") || style.starts_with("popin")) {
// try parsing
float movePerc = 0.f;
if (style.find("%") != std::string::npos) {
Expand Down
102 changes: 83 additions & 19 deletions src/render/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,17 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor

EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS);

// TODO: dedup this with renderallclients
auto preWorkspaceScaleAnim = []() { g_pHyprOpenGL->bindOffMain(); };

auto postWorkspaceScaleAnim = [pMonitor](PHLWORKSPACE workspace) {
g_pHyprOpenGL->bindBackOnMain();
CBox box = CBox{{}, pMonitor->vecPixelSize}.scaleFromCenter(workspace->m_fScaleClients.value());
g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_RenderData.pCurrentMonData->offMainFB.m_cTex, &box, 1.F);
};

std::unordered_map<PHLWORKSPACE, std::vector<std::pair<PHLWINDOW, eRenderPassMode>>> toRender;

// Non-floating main
for (auto& w : g_pCompositor->m_vWindows) {
if (w->isHidden() || (!w->m_bIsMapped && !w->m_bFadingOut))
Expand All @@ -457,12 +468,11 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor
continue;
}

// render the bad boy
renderWindow(w, pMonitor, time, true, RENDER_PASS_MAIN);
toRender[w->m_pWorkspace].emplace_back(w, RENDER_PASS_MAIN);
}

if (lastWindow)
renderWindow(lastWindow, pMonitor, time, true, RENDER_PASS_MAIN);
toRender[lastWindow->m_pWorkspace].emplace_back(lastWindow, RENDER_PASS_MAIN);

// Non-floating popup
for (auto& w : g_pCompositor->m_vWindows) {
Expand All @@ -478,8 +488,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor
if (!shouldRenderWindow(w, pMonitor))
continue;

// render the bad boy
renderWindow(w, pMonitor, time, true, RENDER_PASS_POPUP);
toRender[w->m_pWorkspace].emplace_back(w, RENDER_PASS_POPUP);
}

// floating on top
Expand All @@ -499,9 +508,47 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, PHLWORKSPACE pWor
if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID)
continue; // special on another are rendered as a part of the base pass

// render the bad boy
renderWindow(w, pMonitor, time, true, RENDER_PASS_ALL);
toRender[w->m_pWorkspace].emplace_back(w, RENDER_PASS_ALL);
}

// firstly, render all workspaces in sync, but leave out main workspace
for (auto& [k, v] : toRender) {
if (k == pWorkspace || !k)
continue;

const bool SCALE = k->m_fScaleClients.value() != 1.F && g_pCompositor->getWindowsOnWorkspace(k->m_iID) > 0;

if (SCALE)
preWorkspaceScaleAnim();

for (auto& [window, mode] : v) {
renderWindow(window, pMonitor, time, true, mode);
}

if (SCALE)
postWorkspaceScaleAnim(k);
}

const bool SCALE = pWorkspace->m_fScaleClients.value() != 1.F && g_pCompositor->getWindowsOnWorkspace(pWorkspace->m_iID) > 0;

if (SCALE)
preWorkspaceScaleAnim();

// lastly, render the current ws
if (toRender.contains(pWorkspace)) {
for (auto& [window, mode] : toRender[pWorkspace]) {
renderWindow(window, pMonitor, time, true, mode);
}
}
// and the null ws (windows fading out)
if (toRender.contains(nullptr)) {
for (auto& [window, mode] : toRender[nullptr]) {
renderWindow(window, pMonitor, time, true, mode);
}
}

if (SCALE)
postWorkspaceScaleAnim(pWorkspace);
}

void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool ignoreAllGeometry) {
Expand Down Expand Up @@ -813,11 +860,19 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon
}

void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) {
static auto PDIMSPECIAL = CConfigValue<Hyprlang::FLOAT>("decoration:dim_special");
static auto PBLURSPECIAL = CConfigValue<Hyprlang::INT>("decoration:blur:special");
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
static auto PRENDERTEX = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_logo");
static auto PBACKGROUNDCOLOR = CConfigValue<Hyprlang::INT>("misc:background_color");
static auto PDIMSPECIAL = CConfigValue<Hyprlang::FLOAT>("decoration:dim_special");
static auto PBLURSPECIAL = CConfigValue<Hyprlang::INT>("decoration:blur:special");
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
static auto PRENDERTEX = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_logo");
static auto PBACKGROUNDCOLOR = CConfigValue<Hyprlang::INT>("misc:background_color");

auto preWorkspaceScaleAnim = []() { g_pHyprOpenGL->bindOffMain(); };

auto postWorkspaceScaleAnim = [pMonitor](PHLWORKSPACE workspace) {
g_pHyprOpenGL->bindBackOnMain();
CBox box = CBox{{}, pMonitor->vecPixelSize}.scaleFromCenter(workspace->m_fScaleClients.value());
g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_RenderData.pCurrentMonData->offMainFB.m_cTex, &box, 1.F);
};

SRenderModifData RENDERMODIFDATA;
if (translate != Vector2D{0, 0})
Expand Down Expand Up @@ -936,12 +991,21 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC

// special
for (auto& ws : g_pCompositor->m_vWorkspaces) {
if (ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) {
if (ws->m_bHasFullscreenWindow)
renderWorkspaceWindowsFullscreen(pMonitor, ws, time);
else
renderWorkspaceWindows(pMonitor, ws, time);
}
if (ws->m_fAlpha.value() <= 0.F || !ws->m_bIsSpecialWorkspace)
continue;

const bool SCALE = ws->m_fScaleClients.value() != 1.F && g_pCompositor->getWindowsOnWorkspace(ws->m_iID) > 0;

if (SCALE)
preWorkspaceScaleAnim();

if (ws->m_bHasFullscreenWindow)
renderWorkspaceWindowsFullscreen(pMonitor, ws, time);
else
renderWorkspaceWindows(pMonitor, ws, time);

if (SCALE)
postWorkspaceScaleAnim(ws);
}

// pinned always above
Expand Down Expand Up @@ -1316,7 +1380,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
EMIT_HOOK_EVENT("render", RENDER_POST_MIRROR);
renderCursor = false;
} else {
CBox renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y};
CBox renderBox = CBox{0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y};
renderWorkspace(pMonitor, pMonitor->activeWorkspace, &now, renderBox);

renderLockscreen(pMonitor, &now, renderBox);
Expand Down
Loading