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>
This commit is contained in:
parent
47a7628023
commit
77a06e7e6c
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user