47 const QRect br = region.boundingRect();
48 if (QWindowsContext::verbose > 1)
49 qCDebug(lcQpaBackingStore) <<
__FUNCTION__ <<
this << window << offset << br;
50 QWindowsWindow *rw = QWindowsWindow::windowsWindowOf(window);
53 const bool hasAlpha = rw->format().hasAlpha();
54 const Qt::WindowFlags flags = window->flags();
56 if (rw->isLayered() && hasAlpha && QWindowsWindow::hasNoNativeFrame(rw->handle(), flags)) {
58 QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window);
59 QMargins frameMargins = rw->frameMargins();
60 QRect dirtyRect = br.translated(offset + QPoint(frameMargins.left(), frameMargins.top()));
62 SIZE size = {r.width(), r.height()};
63 POINT ptDst = {r.x(), r.y()};
65 BLENDFUNCTION blend = {AC_SRC_OVER, 0, BYTE(qRound(255.0 * rw->opacity())), AC_SRC_ALPHA};
66 RECT dirty = {dirtyRect.x(), dirtyRect.y(),
67 dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()};
68 UPDATELAYEREDWINDOWINFO info = {
sizeof(info),
nullptr, &ptDst, &size,
69 m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty};
70 const BOOL result = UpdateLayeredWindowIndirect(rw->handle(), &info);
72 qErrnoWarning(
"UpdateLayeredWindowIndirect failed for ptDst=(%d, %d),"
73 " size=(%dx%d), dirty=(%dx%d %d, %d)", r.x(), r.y(),
74 r.width(), r.height(), dirtyRect.width(), dirtyRect.height(),
75 dirtyRect.x(), dirtyRect.y());
77 const HDC dc = rw->getDC();
79 qErrnoWarning(
"%s: GetDC failed",
__FUNCTION__);
83 if (!BitBlt(dc, br.x(), br.y(), br.width(), br.height(),
84 m_image->hdc(), br.x() + offset.x(), br.y() + offset.y(), SRCCOPY)) {
85 const DWORD lastError = GetLastError();
86 if (lastError != ERROR_SUCCESS && lastError != ERROR_INVALID_HANDLE)
87 qErrnoWarning(
int(lastError),
"%s: BitBlt failed",
__FUNCTION__);
93 if (QWindowsContext::verbose > 2 && lcQpaBackingStore().isDebugEnabled()) {
95 const QString fileName = QString::fromLatin1(
"win%1_%2.png").
96 arg(rw->winId()).arg(n++);
97 m_image->image().save(fileName);
98 qCDebug(lcQpaBackingStore) <<
"Wrote " << m_image->image().size() << fileName;
104 if (m_image.isNull() || m_image->image().size() != size) {
105#ifndef QT_NO_DEBUG_OUTPUT
107 qCDebug(lcQpaBackingStore)
108 <<
__FUNCTION__ <<
' ' << window() <<
' ' << size <<
' ' << region
109 <<
" from: " << (m_image.isNull() ? QSize() : m_image->image().size());
112 QImage::Format format = window()->format().hasAlpha() ?
113 QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat();
118 if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha)
119 m_alphaNeedsFill =
true;
121 format = qt_maybeDataCompatibleAlphaVersion(format);
123 QWindowsNativeImage *oldwni = m_image.data();
124 auto *newwni =
new QWindowsNativeImage(size.width(), size.height(), format);
126 if (oldwni && !region.isEmpty()) {
127 const QImage &oldimg(oldwni->image());
128 QImage &newimg(newwni->image());
129 QRegion staticRegion(region);
130 staticRegion &= QRect(0, 0, oldimg.width(), oldimg.height());
131 staticRegion &= QRect(0, 0, newimg.width(), newimg.height());
132 QPainter painter(&newimg);
133 painter.setCompositionMode(QPainter::CompositionMode_Source);
134 for (
const QRect &rect : staticRegion)
135 painter.drawImage(rect, oldimg, rect);
138 m_image.reset(newwni);
Singleton container for all relevant information.