* @brief Creates the drop-shadow as a BorderImage over a shared 9-slice atlas (no per-window * full-window backing); enables the window alpha channel the shadow needs. Skipped * entirely when the shadow is disabled, leaving an opaque frameless window. */
| 939 | * entirely when the shadow is disabled, leaving an opaque frameless window. |
| 940 | */ |
| 941 | void Window::setupFrame() |
| 942 | { |
| 943 | if (!m_shadowEnabled) |
| 944 | return; |
| 945 | |
| 946 | auto* quickWindow = qobject_cast<QQuickWindow*>(m_window.data()); |
| 947 | if (!quickWindow) |
| 948 | return; |
| 949 | |
| 950 | QSurfaceFormat format = quickWindow->format(); |
| 951 | if (format.alphaBufferSize() < 8) { |
| 952 | format.setAlphaBufferSize(8); |
| 953 | quickWindow->setFormat(format); |
| 954 | } |
| 955 | |
| 956 | quickWindow->setColor(Qt::transparent); |
| 957 | |
| 958 | QQmlEngine* engine = qmlEngine(quickWindow); |
| 959 | if (!engine) |
| 960 | return; |
| 961 | |
| 962 | if (!engine->imageProvider(QStringLiteral("csdshadow"))) |
| 963 | engine->addImageProvider(QStringLiteral("csdshadow"), new detail::ShadowImageProvider); |
| 964 | |
| 965 | const QString qml = QStringLiteral("import QtQuick\n" |
| 966 | "BorderImage {\n" |
| 967 | " source: \"image://csdshadow/%1\"\n" |
| 968 | " border { left: %1; right: %1; top: %1; bottom: %1 }\n" |
| 969 | " horizontalTileMode: BorderImage.Stretch\n" |
| 970 | " verticalTileMode: BorderImage.Stretch\n" |
| 971 | "}\n") |
| 972 | .arg(CSD::ShadowRadius); |
| 973 | |
| 974 | QQmlComponent component(engine); |
| 975 | component.setData(qml.toUtf8(), QUrl()); |
| 976 | if (component.isError()) { |
| 977 | for (const auto& error : component.errors()) |
| 978 | qWarning() << "CSD frame QML error:" << error.toString(); |
| 979 | |
| 980 | return; |
| 981 | } |
| 982 | |
| 983 | m_frame = qobject_cast<QQuickItem*>(component.create()); |
| 984 | if (!m_frame) |
| 985 | return; |
| 986 | |
| 987 | m_frame->setParentItem(quickWindow->contentItem()); |
| 988 | m_frame->setZ(-1); |
| 989 | |
| 990 | connect(quickWindow, &QQuickWindow::widthChanged, this, &Window::updateFrameGeometry); |
| 991 | connect(quickWindow, &QQuickWindow::heightChanged, this, &Window::updateFrameGeometry); |
| 992 | |
| 993 | updateFrameGeometry(); |
| 994 | } |
| 995 | |
| 996 | /** |
| 997 | * @brief Creates the 1px window border as four scene-graph edges (no painter, no FBO). |