diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2013-02-06 11:38:26 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-02-06 14:21:44 +0100 |
commit | b3820b12fbded1f173837eee7f7559783e92b46b (patch) | |
tree | c53fa9b6b9b20d28be22baf31abe6be2bc6c459c /src | |
parent | ba2a0d652c3366638fb18218b632de8512fb1c9c (diff) |
Windows: Fix setting of layered windows.
The setting/clearing of WS_EX_LAYERED in the backing store
interfered with the setting/clearing in setWindowOpacity
when combining translucent and non-opaque windows.
Introduce QWindowsWindow::setWindowLayered to handle
it consistently.
Task-number: QTBUG-29010
Task-number: QTBUG-28531
Change-Id: Ib6e2740aae417bdf7b3db9ef7deb646be98df1d6
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsbackingstore.cpp | 6 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.cpp | 48 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.h | 2 |
3 files changed, 38 insertions, 18 deletions
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 792eaf0fdc..0a7ff61b7b 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -88,11 +88,7 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, QWindowsWindow *rw = QWindowsWindow::baseWindowOf(window); #ifndef Q_OS_WINCE - if (rw->format().hasAlpha() && (window->flags() & Qt::FramelessWindowHint)) { - const long wl = GetWindowLong(rw->handle(), GWL_EXSTYLE); - if ((wl & WS_EX_LAYERED) == 0) - SetWindowLong(rw->handle(), GWL_EXSTYLE, wl | WS_EX_LAYERED); - + if (QWindowsWindow::setWindowLayered(rw->handle(), window->flags(), rw->format().hasAlpha(), rw->opacity())) { QRect r = window->frameGeometry(); QPoint frameOffset(window->frameMargins().left(), window->frameMargins().top()); QRect dirtyRect = br.translated(offset + frameOffset); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 42a301cbb2..5d6d4620b7 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -209,22 +209,42 @@ static bool shouldShowMaximizeButton(Qt::WindowFlags flags) return flags & Qt::WindowMaximizeButtonHint; } -static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, qreal level) +// Set the WS_EX_LAYERED flag on a HWND if required. This is required for +// translucent backgrounds, not fully opaque windows and for +// Qt::WindowTransparentForInput (in combination with WS_EX_TRANSPARENT). +bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity) +{ +#ifndef Q_OS_WINCE // maybe needs revisiting WS_EX_LAYERED + const LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + const bool needsLayered = (flags & Qt::WindowTransparentForInput) + || (hasAlpha && (flags & Qt::FramelessWindowHint)) || opacity < 1.0; + const bool isLayered = (exStyle & WS_EX_LAYERED); + if (needsLayered != isLayered) { + if (needsLayered) { + SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED); + } else { + SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED); + } + } + return needsLayered; +#else // !Q_OS_WINCE + Q_UNUSED(hwnd); + Q_UNUSED(flags); + Q_UNUSED(hasAlpha); + Q_UNUSED(opacity); + return false; +#endif // Q_OS_WINCE +} + +static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal level) { #ifdef Q_OS_WINCE // maybe needs revisit WS_EX_LAYERED Q_UNUSED(hwnd); Q_UNUSED(flags); + Q_UNUSED(hasAlpha); Q_UNUSED(level); #else - const long wl = GetWindowLong(hwnd, GWL_EXSTYLE); - const bool isOpaque = level == 1.0 && !(flags & Qt::WindowTransparentForInput); - - if (isOpaque) { - if (wl & WS_EX_LAYERED) - SetWindowLong(hwnd, GWL_EXSTYLE, wl & ~WS_EX_LAYERED); - } else { - if ((wl & WS_EX_LAYERED) == 0) - SetWindowLong(hwnd, GWL_EXSTYLE, wl | WS_EX_LAYERED); + if (QWindowsWindow::setWindowLayered(hwnd, flags, hasAlpha, level)) { if (flags & Qt::FramelessWindowHint) { BLENDFUNCTION blend = {AC_SRC_OVER, 0, (BYTE)(255.0 * level), AC_SRC_ALPHA}; QWindowsContext::user32dll.updateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA); @@ -271,7 +291,7 @@ struct WindowCreationData WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0), topLevel(false), popup(false), dialog(false), desktop(false), - tool(false), embedded(false) {} + tool(false), embedded(false), hasAlpha(false) {} void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0); inline WindowData create(const QWindow *w, const QRect &geometry, QString title) const; @@ -290,6 +310,7 @@ struct WindowCreationData bool desktop; bool tool; bool embedded; + bool hasAlpha; }; QDebug operator<<(QDebug debug, const WindowCreationData &d) @@ -308,6 +329,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag unsigned creationFlags) { isGL = w->surfaceType() == QWindow::OpenGLSurface; + hasAlpha = w->format().hasAlpha(); flags = flagsIn; // Sometimes QWindow doesn't have a QWindow parent but does have a native parent window, @@ -526,7 +548,7 @@ void WindowCreationData::initialize(HWND hwnd, bool frameChange, qreal opacityLe EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); } - setWindowOpacity(hwnd, flags, opacityLevel); + setWindowOpacity(hwnd, flags, hasAlpha, opacityLevel); } else { // child. SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags); } @@ -1471,7 +1493,7 @@ void QWindowsWindow::setOpacity(qreal level) if (m_opacity != level) { m_opacity = level; if (m_data.hwnd) - setWindowOpacity(m_data.hwnd, m_data.flags, level); + setWindowOpacity(m_data.hwnd, m_data.flags, window()->format().hasAlpha(), level); } } diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index c864ba439f..c30b6e62b0 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -216,6 +216,8 @@ public: static inline void *userDataOf(HWND hwnd); static inline void setUserDataOf(HWND hwnd, void *ud); + static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity); + HDC getDC(); void releaseDC(); #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO |