#include "shadowoverlay.h" #include ShadowOverlay::ShadowOverlay(QWidget *parent) : QWidget(parent) { setAttribute(Qt::WA_TransparentForMouseEvents, true); setAttribute(Qt::WA_NoSystemBackground, true); setFocusPolicy(Qt::NoFocus); } void ShadowOverlay::setShadow(int blurRadius, int cornerRadius, const QColor &color) { m_blurRadius = blurRadius; m_cornerRadius = cornerRadius; m_color = color; m_patch = NinePatchShadow{}; // force rebuild on next paint m_builtDpr = 0.0; update(); } void ShadowOverlay::setBodyCutout(bool on) { if (m_bodyCutout == on) { return; } m_bodyCutout = on; update(); } void ShadowOverlay::ensurePixmap(qreal dpr) { if (!m_patch.isNull() && qFuzzyCompare(m_builtDpr, dpr)) { return; } m_patch = ShadowPixmap::make(m_blurRadius, m_cornerRadius, m_color, dpr); m_builtDpr = dpr; } void ShadowOverlay::paintEvent(QPaintEvent *) { const qreal dpr = devicePixelRatioF(); ensurePixmap(dpr); if (m_patch.isNull()) { return; } const int b = m_patch.border; const int t = m_patch.total; const qreal s = m_patch.dpr; const QRect r = rect(); // Degenerate target (smaller than the two fixed borders): nothing sensible // to slice, skip rather than draw garbage. if (r.width() < 2 * b || r.height() < 2 * b) { return; } // 3x3 grid: corners fixed, edges/centre stretched. Target columns/rows are // logical; source columns/rows are physical (pixmap carries no dpr). const int xt[4] = {r.left(), r.left() + b, r.right() + 1 - b, r.right() + 1}; const int yt[4] = {r.top(), r.top() + b, r.bottom() + 1 - b, r.bottom() + 1}; const qreal xs[4] = {0.0, b * s, (t - b) * s, t * s}; const qreal ys[4] = {0.0, b * s, (t - b) * s, t * s}; QPainter p(this); if (m_bodyCutout) { // Paint only the ring outside the target's footprint. const int reachPx = reach(); const QRect body = r.adjusted(reachPx, reachPx, -reachPx, -reachPx); if (body.isValid()) { p.setClipRegion(QRegion(r).subtracted(QRegion(body))); } } for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { const QRectF target(xt[i], yt[j], xt[i + 1] - xt[i], yt[j + 1] - yt[j]); const QRectF source(xs[i], ys[j], xs[i + 1] - xs[i], ys[j + 1] - ys[j]); p.drawPixmap(target, m_patch.pixmap, source); } } }