diff options
author | Matt Hoosier <matt.hoosier@garmin.com> | 2013-05-16 11:01:23 -0500 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-05-23 20:01:40 +0200 |
commit | 77a06e7e6c517003585ba53b9776e90c8d290e84 (patch) | |
tree | a685f2de81eae4a29578bdfa34c05c2a8163670d /src | |
parent | 47a7628023610904c6ac52e23fa289f75f349b4e (diff) |
QNX: Support window translucency
A few tactical changes were necessary to do this:
* The root window's buffer must be the full size of the window in
order for transparency to work. We now transition this buffer
to full-size upon first request of some QWindow to be translucent.
At the same time the root window is transitioned to being full-
screen, we also set its alpha blending mode to Source-Over in
order to permit lower z-ordered apps to show through.
* Set the root window's buffer position to (0, 0) to avoid a momentary
flicker of unpainted pixels on the far right-hand border as a
translucent window comes on-screen.
* Use Source-Over alpha blending for normal child windows too.
The QtGui core logic for setting the backing surface pixel format to
something with an alpha channel if Qt::WA_TranslucentBackground is
set on the toplevel QWidget already accomplished the remainder of
the work.
Change-Id: I1c2b31aa6323b4555fa194313f0f5e06ada494fc
Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com>
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
Reviewed-by: Andreas Holzammer <andreas.holzammer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/platforms/qnx/qqnxrootwindow.cpp | 59 | ||||
-rw-r--r-- | src/plugins/platforms/qnx/qqnxrootwindow.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/qnx/qqnxwindow.cpp | 14 |
3 files changed, 72 insertions, 5 deletions
diff --git a/src/plugins/platforms/qnx/qqnxrootwindow.cpp b/src/plugins/platforms/qnx/qqnxrootwindow.cpp index dddadb5ca8..5d58890c51 100644 --- a/src/plugins/platforms/qnx/qqnxrootwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrootwindow.cpp @@ -60,7 +60,8 @@ static const int MAGIC_ZORDER_FOR_NO_NAV = 10; QQnxRootWindow::QQnxRootWindow(const QQnxScreen *screen) : m_screen(screen), m_window(0), - m_windowGroupName() + m_windowGroupName(), + m_translucent(false) { qRootWindowDebug() << Q_FUNC_INFO; // Create one top-level QNX window to act as a container for child windows @@ -122,7 +123,10 @@ QQnxRootWindow::QQnxRootWindow(const QQnxScreen *screen) if (result != 0) qFatal("QQnxRootWindow: failed to set window size, errno=%d", errno); - // Fill the window with solid black + // Fill the window with solid black. Note that the LSB of the pixel value + // 0x00000000 just happens to be 0x00, so if and when this root window's + // alpha blending mode is changed from None to Source-Over, it will then + // be interpreted as transparent. errno = 0; val[0] = 0; result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_COLOR, val); @@ -152,13 +156,62 @@ QQnxRootWindow::QQnxRootWindow(const QQnxScreen *screen) qFatal("QQnxRootWindow: failed to set window source size, errno=%d", errno); errno = 0; - val[0] = 1; + val[0] = 0; val[1] = 0; result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_POSITION, val); if (result != 0) qFatal("QQnxRootWindow: failed to set window source position, errno=%d", errno); createWindowGroup(); + + // Don't post yet. This will be lazily done from QQnxScreen upon first posting of + // a child window. Doing it now pre-emptively would create a flicker if one of + // the QWindow's about to be created sets its Qt::WA_TranslucentBackground flag + // and immediately triggers the buffer re-creation in makeTranslucent(). +} + +void QQnxRootWindow::makeTranslucent() +{ + if (m_translucent) + return; + + int result; + + errno = 0; + result = screen_destroy_window_buffers(m_window); + if (result != 0) { + qFatal("QQnxRootWindow: failed to destroy window buffer, errno=%d", errno); + } + + QRect geometry = m_screen->geometry(); + errno = 0; + int val[2]; + val[0] = geometry.width(); + val[1] = geometry.height(); + result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val); + if (result != 0) { + qFatal("QQnxRootWindow: failed to set window buffer size, errno=%d", errno); + } + + errno = 0; + result = screen_create_window_buffers(m_window, 1); + if (result != 0) { + qFatal("QQNX: failed to create window buffer, errno=%d", errno); + } + + // Install an alpha channel on the root window. + // + // This is necessary in order to avoid interfering with any particular + // toplevel widget's QQnxWindow window instance from showing transparent + // if it desires. + errno = 0; + val[0] = SCREEN_TRANSPARENCY_SOURCE_OVER; + result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, val); + if (result != 0) { + qFatal("QQnxRootWindow: failed to set window transparency, errno=%d", errno); + } + + m_translucent = true; post(); } diff --git a/src/plugins/platforms/qnx/qqnxrootwindow.h b/src/plugins/platforms/qnx/qqnxrootwindow.h index aae1563c95..ea7c7faace 100644 --- a/src/plugins/platforms/qnx/qqnxrootwindow.h +++ b/src/plugins/platforms/qnx/qqnxrootwindow.h @@ -66,6 +66,8 @@ public: void resize(const QSize &size); + void makeTranslucent(); + QByteArray groupName() const { return m_windowGroupName; } private: @@ -74,6 +76,8 @@ private: const QQnxScreen *m_screen; screen_window_t m_window; QByteArray m_windowGroupName; + + bool m_translucent; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index f4cbb0e9db..7a1ffb98b8 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -117,9 +117,13 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context) if (result != 0) qFatal("QQnxWindow: failed to set window alpha mode, errno=%d", errno); - // Make the window opaque + // Blend the window with Source Over Porter-Duff behavior onto whatever's + // behind it. + // + // If the desired use-case is opaque, the Widget painting framework will + // already fill in the alpha channel with full opacity. errno = 0; - val = SCREEN_TRANSPARENCY_NONE; + val = SCREEN_TRANSPARENCY_SOURCE_OVER; result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, &val); if (result != 0) qFatal("QQnxWindow: failed to set window transparency, errno=%d", errno); @@ -370,6 +374,12 @@ void QQnxWindow::setBufferSize(const QSize &size) qWarning() << "QQnxWindow: Buffer size was" << size; qFatal("QQnxWindow: failed to create window buffers, errno=%d", errno); + // If the child window has been configured for transparency, lazily create + // a full-screen buffer to back the root window. + if (window()->requestedFormat().hasAlpha()) { + m_screen->rootWindow()->makeTranslucent(); + } + // check if there are any buffers available int bufferCount = 0; result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &bufferCount); |