Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qwindowsbackingstore.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "qwindowswindow.h"
6#include "qwindowscontext.h"
7
8#include <QtGui/qwindow.h>
9#include <QtGui/qpainter.h>
10#include <QtGui/private/qwindowsnativeimage_p.h>
11#include <private/qhighdpiscaling_p.h>
12#include <private/qimage_p.h>
13
14#include <QtCore/qdebug.h>
15
17
26 m_alphaNeedsFill(false)
27{
28 qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window;
29}
30
32{
33 qCDebug(lcQpaBackingStore) << __FUNCTION__ << this;
34}
35
37{
38 Q_ASSERT(!m_image.isNull());
39 return &m_image->image();
40}
41
43 const QPoint &offset)
44{
46
47 const QRect br = region.boundingRect();
49 qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window << offset << br;
51 Q_ASSERT(rw);
52
53 const bool hasAlpha = rw->format().hasAlpha();
54 const Qt::WindowFlags flags = window->flags();
56 // Windows with alpha: Use blend function to update.
57 QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window);
58 QMargins frameMargins = rw->frameMargins();
59 QRect dirtyRect = br.translated(offset + QPoint(frameMargins.left(), frameMargins.top()));
60
61 SIZE size = {r.width(), r.height()};
62 POINT ptDst = {r.x(), r.y()};
63 POINT ptSrc = {0, 0};
64 BLENDFUNCTION blend = {AC_SRC_OVER, 0, BYTE(qRound(255.0 * rw->opacity())), AC_SRC_ALPHA};
65 RECT dirty = {dirtyRect.x(), dirtyRect.y(),
66 dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()};
67 UPDATELAYEREDWINDOWINFO info = {sizeof(info), nullptr, &ptDst, &size,
68 m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty};
69 const BOOL result = UpdateLayeredWindowIndirect(rw->handle(), &info);
70 if (!result)
71 qErrnoWarning("UpdateLayeredWindowIndirect failed for ptDst=(%d, %d),"
72 " size=(%dx%d), dirty=(%dx%d %d, %d)", r.x(), r.y(),
73 r.width(), r.height(), dirtyRect.width(), dirtyRect.height(),
74 dirtyRect.x(), dirtyRect.y());
75 } else {
76 const HDC dc = rw->getDC();
77 if (!dc) {
78 qErrnoWarning("%s: GetDC failed", __FUNCTION__);
79 return;
80 }
81
82 if (!BitBlt(dc, br.x(), br.y(), br.width(), br.height(),
83 m_image->hdc(), br.x() + offset.x(), br.y() + offset.y(), SRCCOPY)) {
84 const DWORD lastError = GetLastError(); // QTBUG-35926, QTBUG-29716: may fail after lock screen.
85 if (lastError != ERROR_SUCCESS && lastError != ERROR_INVALID_HANDLE)
86 qErrnoWarning(int(lastError), "%s: BitBlt failed", __FUNCTION__);
87 }
88 rw->releaseDC();
89 }
90
91 // Write image for debug purposes.
92 if (QWindowsContext::verbose > 2 && lcQpaBackingStore().isDebugEnabled()) {
93 static int n = 0;
94 const QString fileName = QString::fromLatin1("win%1_%2.png").
95 arg(rw->winId()).arg(n++);
96 m_image->image().save(fileName);
97 qCDebug(lcQpaBackingStore) << "Wrote " << m_image->image().size() << fileName;
98 }
99}
100
102{
103 if (m_image.isNull() || m_image->image().size() != size) {
104#ifndef QT_NO_DEBUG_OUTPUT
105 if (QWindowsContext::verbose && lcQpaBackingStore().isDebugEnabled()) {
106 qCDebug(lcQpaBackingStore)
107 << __FUNCTION__ << ' ' << window() << ' ' << size << ' ' << region
108 << " from: " << (m_image.isNull() ? QSize() : m_image->image().size());
109 }
110#endif
113
114 // The backingstore composition (enabling render-to-texture widgets)
115 // punches holes in the backingstores using the alpha channel. Hence
116 // the need for a true alpha format.
118 m_alphaNeedsFill = true;
119 else // upgrade but here we know app painting does not rely on alpha hence no need to fill
121
122 QWindowsNativeImage *oldwni = m_image.data();
123 auto *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
124
125 if (oldwni && !region.isEmpty()) {
126 const QImage &oldimg(oldwni->image());
127 QImage &newimg(newwni->image());
128 QRegion staticRegion(region);
129 staticRegion &= QRect(0, 0, oldimg.width(), oldimg.height());
130 staticRegion &= QRect(0, 0, newimg.width(), newimg.height());
131 QPainter painter(&newimg);
133 for (const QRect &rect : staticRegion)
134 painter.drawImage(rect, oldimg, rect);
135 }
136
137 m_image.reset(newwni);
138 }
139}
140
141Q_GUI_EXPORT void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
142
143bool QWindowsBackingStore::scroll(const QRegion &area, int dx, int dy)
144{
145 if (m_image.isNull() || m_image->image().isNull())
146 return false;
147
148 const QPoint offset(dx, dy);
149 const QRect rect = area.boundingRect();
151
152 return true;
153}
154
156{
158 qCDebug(lcQpaBackingStore) <<__FUNCTION__ << region;
159
160 if (m_alphaNeedsFill) {
161 QPainter p(&m_image->image());
162 p.setCompositionMode(QPainter::CompositionMode_Source);
163 const QColor blank = Qt::transparent;
164 for (const QRect &r : region)
165 p.fillRect(r, blank);
166 }
167}
168
170{
171 if (!m_image.isNull())
172 return m_image->hdc();
173 return nullptr;
174}
175
177{
178 if (m_image.isNull()) {
179 qCWarning(lcQpaBackingStore) <<__FUNCTION__ << "Image is null.";
180 return QImage();
181 }
182 return m_image.data()->image();
183}
184
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
\inmodule QtGui
Definition qimage.h:37
static QPixelFormat toPixelFormat(QImage::Format format) noexcept
Converts format into a QPixelFormat.
Definition qimage.cpp:5721
QSize size() const
Returns the size of the image, i.e.
int width() const
Returns the width of the image.
bool save(const QString &fileName, const char *format=nullptr, int quality=-1) const
Saves the image to the file with the given fileName, using the given image file format and quality fa...
Definition qimage.cpp:3870
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition qimage.cpp:1197
int height() const
Returns the height of the image.
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
\inmodule QtCore
Definition qmargins.h:23
constexpr int left() const noexcept
Returns the left margin.
Definition qmargins.h:110
constexpr int top() const noexcept
Returns the top margin.
Definition qmargins.h:113
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Draws the rectangular portion source of the given image into the target rectangle in the paint device...
@ CompositionMode_Source
Definition qpainter.h:101
The QPlatformBackingStore class provides the drawing area for top-level windows.
QWindow * window() const
Returns a pointer to the top-level window associated with this surface.
\inmodule QtCore\reentrant
Definition qpoint.h:23
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
constexpr QRect translated(int dx, int dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:260
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:187
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
QRect boundingRect() const noexcept
Returns the bounding rectangle of this region.
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
T * data() const noexcept
Returns the value of the pointer referenced by this object.
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
bool hasAlpha() const
Returns true if the alpha buffer size is greater than zero.
\inmodule QtGui
Definition qwindow.h:63
Qt::WindowFlags flags
the window flags of the window
Definition qwindow.h:79
QSurfaceFormat format() const override
Returns the actual format of this window.
Definition qwindow.cpp:888
void beginPaint(const QRegion &) override
This function is called before painting onto the surface begins, with the region in which the paintin...
QPaintDevice * paintDevice() override
Implement this function to return the appropriate paint device.
bool scroll(const QRegion &area, int dx, int dy) override
Scrolls the given area dx pixels to the right and dy downward; both dx and dy may be negative.
QWindowsBackingStore(QWindow *window)
void flush(QWindow *window, const QRegion &region, const QPoint &offset) override
Flushes the given region from the specified window.
void resize(const QSize &size, const QRegion &r) override
QImage toImage() const override
Implemented in subclasses to return the content of the backingstore as a QImage.
WId winId() const override
Reimplement in subclasses to return a handle to the native window.
Windows Native image.
static QImage::Format systemFormat()
Raster or OpenGL Window.
static QWindowsWindow * windowsWindowOf(const QWindow *w)
HDC getDC()
Allocates a HDC for the window or returns the temporary one obtained from WinAPI BeginPaint within a ...
qreal opacity() const
static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity)
QSurfaceFormat format() const override
Returns the actual surface format of the window.
QMargins frameMargins() const override
void releaseDC()
Releases the HDC for the window or does nothing in case it was obtained from WinAPI BeginPaint within...
HWND handle() const override
rect
[4]
void qErrnoWarning(const char *msg,...)
T toNativePixels(const T &value, const C *context)
Combined button and popup list for selecting options.
@ transparent
Definition qnamespace.h:46
@ FramelessWindowHint
Definition qnamespace.h:224
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
static int area(const QSize &s)
Definition qicon.cpp:152
QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format)
Definition qimage_p.h:362
#define qCWarning(category,...)
#define qCDebug(category,...)
#define SIZE(large, small, mini)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLbitfield flags
GLenum GLuint GLintptr offset
GLfloat n
GLint GLsizei GLsizei GLenum format
GLint void * img
Definition qopenglext.h:233
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
static bool hasAlpha(const QImage &image)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(*) void arg)
Q_GUI_EXPORT void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
QFileInfo info(fileName)
[8]
QPainter painter(this)
[7]
aWidget window() -> setWindowTitle("New Window Title")
[2]