mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-04 14:11:59 -07:00
renderer/animations: Fix various inaccurate damage tracking issues and offsets (#5297)
This commit is contained in:
@@ -211,7 +211,7 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = NEARESTNEIGHBORSET;
|
||||
}
|
||||
|
||||
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWorkspace* pWorkspace) {
|
||||
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
|
||||
CBox geometry = pWindow->getFullWindowBoundingBox();
|
||||
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, geometry.pWlr()))
|
||||
@@ -234,9 +234,12 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWo
|
||||
}
|
||||
}
|
||||
|
||||
if (pWindow->m_iWorkspaceID == pWorkspace->m_iID && pWorkspace->m_iMonitorID == pMonitor->ID)
|
||||
if (pWindow->m_iMonitorID == pMonitor->ID)
|
||||
return true;
|
||||
|
||||
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) && pWindow->m_iMonitorID != pMonitor->ID)
|
||||
return false;
|
||||
|
||||
// if not, check if it maybe is active on a different monitor.
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */)
|
||||
return !pWindow->m_bIsFullscreen; // Do not draw fullscreen windows on other monitors
|
||||
@@ -244,12 +247,20 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWo
|
||||
if (pMonitor->specialWorkspaceID == pWindow->m_iWorkspaceID)
|
||||
return true;
|
||||
|
||||
// if window is tiled and it's flying in, don't render on other mons (for slide)
|
||||
if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition.isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_iMonitorID != pMonitor->ID)
|
||||
return false;
|
||||
|
||||
if (pWindow->m_vRealPosition.isBeingAnimated()) {
|
||||
if (PWINDOWWORKSPACE && !PWINDOWWORKSPACE->m_bIsSpecialWorkspace && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated())
|
||||
return false;
|
||||
// render window if window and monitor intersect
|
||||
// (when moving out of or through a monitor)
|
||||
CBox windowBox = pWindow->getFullWindowBoundingBox();
|
||||
CBox windowBox = pWindow->getFullWindowBoundingBox();
|
||||
if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated())
|
||||
windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value());
|
||||
windowBox.translate(pWindow->m_vFloatingOffset);
|
||||
|
||||
const CBox monitorBox = {pMonitor->vecPosition, pMonitor->vecSize};
|
||||
if (!windowBox.intersection(monitorBox).empty())
|
||||
return true;
|
||||
@@ -292,7 +303,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp
|
||||
|
||||
// loop over the tiled windows that are fading out
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
if (!shouldRenderWindow(w.get(), pMonitor))
|
||||
continue;
|
||||
|
||||
if (w->m_fAlpha.value() == 0.f)
|
||||
@@ -309,7 +320,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp
|
||||
|
||||
// and floating ones too
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
if (!shouldRenderWindow(w.get(), pMonitor))
|
||||
continue;
|
||||
|
||||
if (w->m_fAlpha.value() == 0.f)
|
||||
@@ -345,7 +356,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp
|
||||
if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
if (shouldRenderWindow(w.get(), pMonitor))
|
||||
renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL);
|
||||
|
||||
if (w->m_iWorkspaceID != pWorkspace->m_iID)
|
||||
@@ -388,7 +399,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork
|
||||
if (w->m_bIsFloating)
|
||||
continue; // floating are in the second pass
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
if (!shouldRenderWindow(w.get(), pMonitor))
|
||||
continue;
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
@@ -418,7 +429,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork
|
||||
if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
if (!shouldRenderWindow(w.get(), pMonitor))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
@@ -433,7 +444,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork
|
||||
if (!w->m_bIsFloating || w->m_bPinned)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
if (!shouldRenderWindow(w.get(), pMonitor))
|
||||
continue;
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
@@ -510,47 +521,16 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha));
|
||||
}
|
||||
|
||||
// clip box for animated offsets
|
||||
const Vector2D PREOFFSETPOS = {renderdata.x, renderdata.y};
|
||||
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned && !pWindow->m_bIsFullscreen) {
|
||||
Vector2D offset;
|
||||
|
||||
if (PWORKSPACE->m_vRenderOffset.value().x != 0) {
|
||||
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().x / PWSMON->vecSize.x;
|
||||
const auto WINBB = pWindow->getFullWindowBoundingBox();
|
||||
|
||||
if (WINBB.x < PWSMON->vecPosition.x) {
|
||||
offset.x = (PWSMON->vecPosition.x - WINBB.x) * PROGRESS;
|
||||
} else if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x) {
|
||||
offset.x = (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS;
|
||||
}
|
||||
} else if (PWORKSPACE->m_vRenderOffset.value().y != 0) {
|
||||
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().y / PWSMON->vecSize.y;
|
||||
const auto WINBB = pWindow->getFullWindowBoundingBox();
|
||||
|
||||
if (WINBB.y < PWSMON->vecPosition.y) {
|
||||
offset.y = (PWSMON->vecPosition.y - WINBB.y) * PROGRESS;
|
||||
} else if (WINBB.y + WINBB.height > PWSMON->vecPosition.y + PWSMON->vecSize.y) {
|
||||
offset.y = (WINBB.y + WINBB.width - PWSMON->vecPosition.y - PWSMON->vecSize.y) * PROGRESS;
|
||||
}
|
||||
}
|
||||
|
||||
renderdata.x += offset.x;
|
||||
renderdata.y += offset.y;
|
||||
}
|
||||
renderdata.x += pWindow->m_vFloatingOffset.x;
|
||||
renderdata.y += pWindow->m_vFloatingOffset.y;
|
||||
|
||||
// if window is floating and we have a slide animation, clip it to its full bb
|
||||
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) {
|
||||
CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.value()).scale(pMonitor->scale);
|
||||
CRegion rg =
|
||||
pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.value() + pWindow->m_vFloatingOffset).scale(pMonitor->scale);
|
||||
g_pHyprOpenGL->m_RenderData.clipBox = rg.getExtents();
|
||||
}
|
||||
|
||||
// if window is tiled and it's flying in, don't render on other mons (for slide)
|
||||
if (!ignorePosition && !pWindow->m_bIsFloating && pWindow->m_vRealPosition.isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_iMonitorID != pMonitor->ID)
|
||||
return;
|
||||
|
||||
// render window decorations first, if not fullscreen full
|
||||
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) {
|
||||
|
||||
@@ -569,14 +549,14 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
if (wd->getDecorationLayer() != DECORATION_LAYER_BOTTOM)
|
||||
continue;
|
||||
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS);
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha);
|
||||
}
|
||||
|
||||
for (auto& wd : pWindow->m_dWindowDecorations) {
|
||||
if (wd->getDecorationLayer() != DECORATION_LAYER_UNDER)
|
||||
continue;
|
||||
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS);
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,7 +581,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
if (wd->getDecorationLayer() != DECORATION_LAYER_OVER)
|
||||
continue;
|
||||
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS);
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,7 +642,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
if (wd->getDecorationLayer() != DECORATION_LAYER_OVERLAY)
|
||||
continue;
|
||||
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS);
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -861,7 +841,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace*
|
||||
if (!w->m_bPinned || !w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
if (!shouldRenderWindow(w.get(), pMonitor))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
@@ -1739,15 +1719,22 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou
|
||||
damageBox.pixman()->extents.x2 - damageBox.pixman()->extents.x1, damageBox.pixman()->extents.y2 - damageBox.pixman()->extents.y1);
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
void CHyprRenderer::damageWindow(CWindow* pWindow, bool forceFull) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
CBox damageBox = pWindow->getFullWindowBoundingBox();
|
||||
CBox windowBox = pWindow->getFullWindowBoundingBox();
|
||||
const auto PWINDOWWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned)
|
||||
windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value());
|
||||
windowBox.translate(pWindow->m_vFloatingOffset);
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
CBox fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
|
||||
fixedDamageBox.scale(m->scale);
|
||||
m->addDamage(&fixedDamageBox);
|
||||
if (g_pHyprRenderer->shouldRenderWindow(pWindow, m.get()) || forceFull) { // only damage if window is rendered on monitor
|
||||
CBox fixedDamageBox = {windowBox.x - m->vecPosition.x, windowBox.y - m->vecPosition.y, windowBox.width, windowBox.height};
|
||||
fixedDamageBox.scale(m->scale);
|
||||
m->addDamage(&fixedDamageBox);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& wd : pWindow->m_dWindowDecorations)
|
||||
@@ -1756,7 +1743,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
static auto PLOGDAMAGE = CConfigValue<Hyprlang::INT>("debug:log_damage");
|
||||
|
||||
if (*PLOGDAMAGE)
|
||||
Debug::log(LOG, "Damage: Window ({}): xy: {}, {} wh: {}, {}", pWindow->m_szTitle, damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
||||
Debug::log(LOG, "Damage: Window ({}): xy: {}, {} wh: {}, {}", pWindow->m_szTitle, windowBox.x, windowBox.y, windowBox.width, windowBox.height);
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||
|
Reference in New Issue
Block a user