From 77a06e7e6c517003585ba53b9776e90c8d290e84 Mon Sep 17 00:00:00 2001 From: Matt Hoosier Date: Thu, 16 May 2013 11:01:23 -0500 Subject: 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 Reviewed-by: Thomas McGuire Reviewed-by: Rafael Roquetto Reviewed-by: Andreas Holzammer --- src/plugins/platforms/qnx/qqnxrootwindow.cpp | 59 ++++++++++++++++++++++++++-- src/plugins/platforms/qnx/qqnxrootwindow.h | 4 ++ src/plugins/platforms/qnx/qqnxwindow.cpp | 14 ++++++- 3 files changed, 72 insertions(+), 5 deletions(-) (limited to 'src') 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); -- cgit v1.2.3