diff --git a/src/scene/workspacescene.cpp b/src/scene/workspacescene.cpp index b9de952a2c..365eb9efd1 100644 --- a/src/scene/workspacescene.cpp +++ b/src/scene/workspacescene.cpp @@ -241,14 +241,29 @@ static void resetRepaintsHelper(Item *item, SceneDelegate *delegate) } } -static void accumulateRepaints(Item *item, SceneDelegate *delegate, QRegion *repaints) +static void accumulateRepaints(Item *item, SceneDelegate *delegate, QRegion *repaints, const bool padDamage) { - *repaints += item->repaints(delegate); + if (!padDamage) { + *repaints += item->repaints(delegate); + } else { + const auto padding = 1; + + for (const QRect region : item->repaints(delegate)) { + if (region.isEmpty() || region == infiniteRegion()) { + *repaints += region; + continue; + } + + *repaints += QRect{region.x() - padding, region.y() - padding, + region.width() + 2 * padding, region.height() + 2 * padding}; + } + } + item->resetRepaints(delegate); const auto childItems = item->childItems(); for (Item *childItem : childItems) { - accumulateRepaints(childItem, delegate, repaints); + accumulateRepaints(childItem, delegate, repaints, padDamage); } } @@ -275,11 +290,17 @@ void WorkspaceScene::preparePaintGenericScreen() void WorkspaceScene::preparePaintSimpleScreen() { + // if a fractional scale factor is used, pad the damage to avoid visual + // glitches due to rounding errors (floating point arithmetic) and/or the + // use of GL_LINEAR in the pipeline + const auto scale = painted_screen->scale(); + const bool padDamage = std::trunc(scale) != scale; + for (WindowItem *windowItem : std::as_const(stacking_order)) { Window *window = windowItem->window(); WindowPrePaintData data; data.mask = m_paintContext.mask; - accumulateRepaints(windowItem, painted_delegate, &data.paint); + accumulateRepaints(windowItem, painted_delegate, &data.paint, padDamage); // Clip out the decoration for opaque windows; the decoration is drawn in the second pass. if (window->opacity() == 1.0) { @@ -314,7 +335,7 @@ void WorkspaceScene::preparePaintSimpleScreen() } if (m_dndIcon) { - accumulateRepaints(m_dndIcon.get(), painted_delegate, &m_paintContext.damage); + accumulateRepaints(m_dndIcon.get(), painted_delegate, &m_paintContext.damage, padDamage); } }