QNX: Manage foreign mmrenderer windows

Manage and correctly set the z-order of a foreign created mmrenderer window by
QtMultimedia

Task-number: QTBUG-33816
Change-Id: I46273b945bf10991462fa72eb1ec8d00b0648988
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
This commit is contained in:
Rafael Roquetto 2013-10-18 18:36:23 -03:00 committed by The Qt Project
parent ae52bba5d4
commit cf239f69e1
6 changed files with 125 additions and 10 deletions

View File

@ -42,6 +42,7 @@
#include "qqnxnativeinterface.h" #include "qqnxnativeinterface.h"
#include "qqnxscreen.h" #include "qqnxscreen.h"
#include "qqnxwindow.h"
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <QtGui/QWindow> #include <QtGui/QWindow>
@ -70,4 +71,12 @@ void *QQnxNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q
return 0; return 0;
} }
void QQnxNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value)
{
if (name == QStringLiteral("mmRendererWindowName")) {
QQnxWindow *qnxWindow = static_cast<QQnxWindow*>(window);
qnxWindow->setMMRendererWindowName(value.toString());
}
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -51,6 +51,7 @@ class QQnxNativeInterface : public QPlatformNativeInterface
public: public:
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window); void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen); void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -119,6 +119,38 @@ static QSize determineScreenSize(screen_display_t display, bool primaryScreen) {
#endif #endif
} }
static QQnxWindow *findMultimediaWindow(const QList<QQnxWindow*> windows,
const QByteArray &mmWindowId)
{
Q_FOREACH (QQnxWindow *sibling, windows) {
if (sibling->mmRendererWindowName() == mmWindowId)
return sibling;
QQnxWindow *mmWindow = findMultimediaWindow(sibling->children(), mmWindowId);
if (mmWindow)
return mmWindow;
}
return 0;
}
static QQnxWindow *findMultimediaWindow(const QList<QQnxWindow*> windows,
screen_window_t mmWindowId)
{
Q_FOREACH (QQnxWindow *sibling, windows) {
if (sibling->mmRendererWindow() == mmWindowId)
return sibling;
QQnxWindow *mmWindow = findMultimediaWindow(sibling->children(), mmWindowId);
if (mmWindow)
return mmWindow;
}
return 0;
}
QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display, bool primaryScreen) QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display, bool primaryScreen)
: m_screenContext(screenContext), : m_screenContext(screenContext),
m_display(display), m_display(display),
@ -585,6 +617,19 @@ void QQnxScreen::addUnderlayWindow(screen_window_t window)
updateHierarchy(); updateHierarchy();
} }
void QQnxScreen::addMultimediaWindow(const QByteArray &id, screen_window_t window)
{
// find the QnxWindow this mmrenderer window is related to
QQnxWindow *mmWindow = findMultimediaWindow(m_childWindows, id);
if (!mmWindow)
return;
mmWindow->setMMRendererWindow(window);
updateHierarchy();
}
void QQnxScreen::removeOverlayOrUnderlayWindow(screen_window_t window) void QQnxScreen::removeOverlayOrUnderlayWindow(screen_window_t window)
{ {
const int numRemoved = m_overlays.removeAll(window) + m_underlays.removeAll(window); const int numRemoved = m_overlays.removeAll(window) + m_underlays.removeAll(window);
@ -610,17 +655,35 @@ void QQnxScreen::newWindowCreated(void *window)
zorder = 0; zorder = 0;
} }
char windowNameBuffer[256] = { 0 };
QByteArray windowName;
if (screen_get_window_property_cv(windowHandle, SCREEN_PROPERTY_ID_STRING,
sizeof(windowNameBuffer) - 1, windowNameBuffer) != 0) {
qWarning("QQnx: Failed to get id for window, errno=%d", errno);
}
windowName = QByteArray(windowNameBuffer);
if (display == nativeDisplay()) { if (display == nativeDisplay()) {
// A window was created on this screen. If we don't know about this window yet, it means // A window was created on this screen. If we don't know about this window yet, it means
// it was not created by Qt, but by some foreign library like the multimedia renderer, which // it was not created by Qt, but by some foreign library like the multimedia renderer, which
// creates an overlay window when playing a video. // creates an overlay window when playing a video.
// //
// Treat all foreign windows as overlays or underlays here. // Treat all foreign windows as overlays, underlays or as windows
// created by the BlackBerry QtMultimedia plugin.
// //
// Assume that if a foreign window already has a Z-Order both negative and // In the case of the BlackBerry QtMultimedia plugin, we need to
// "attach" the foreign created mmrenderer window to the correct
// platform window (usually the one belonging to QVideoWidget) to
// ensure proper z-ordering.
//
// Otherwise, assume that if a foreign window already has a Z-Order both negative and
// less than the default Z-Order installed by mmrender on windows it creates, // less than the default Z-Order installed by mmrender on windows it creates,
// the windows should be treated as an underlay. Otherwise, we treat it as an overlay. // the windows should be treated as an underlay. Otherwise, we treat it as an overlay.
if (!findWindow(windowHandle)) { if (!windowName.isEmpty() && windowName.startsWith("BbVideoWindowControl")) {
addMultimediaWindow(windowName, windowHandle);
} else if (!findWindow(windowHandle)) {
if (zorder <= MAX_UNDERLAY_ZORDER) if (zorder <= MAX_UNDERLAY_ZORDER)
addUnderlayWindow(windowHandle); addUnderlayWindow(windowHandle);
else else
@ -634,6 +697,12 @@ void QQnxScreen::windowClosed(void *window)
{ {
Q_ASSERT(thread() == QThread::currentThread()); Q_ASSERT(thread() == QThread::currentThread());
const screen_window_t windowHandle = reinterpret_cast<screen_window_t>(window); const screen_window_t windowHandle = reinterpret_cast<screen_window_t>(window);
QQnxWindow *mmWindow = findMultimediaWindow(m_childWindows, windowHandle);
if (mmWindow)
mmWindow->clearMMRendererWindow();
else
removeOverlayOrUnderlayWindow(windowHandle); removeOverlayOrUnderlayWindow(windowHandle);
} }

View File

@ -119,6 +119,7 @@ private:
void resizeWindows(const QRect &previousScreenGeometry); void resizeWindows(const QRect &previousScreenGeometry);
void addOverlayWindow(screen_window_t window); void addOverlayWindow(screen_window_t window);
void addUnderlayWindow(screen_window_t window); void addUnderlayWindow(screen_window_t window);
void addMultimediaWindow(const QByteArray &id, screen_window_t window);
void removeOverlayOrUnderlayWindow(screen_window_t window); void removeOverlayOrUnderlayWindow(screen_window_t window);
QWindow *topMostChildWindow() const; QWindow *topMostChildWindow() const;

View File

@ -77,7 +77,8 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context)
m_parentWindow(0), m_parentWindow(0),
m_visible(false), m_visible(false),
m_exposed(true), m_exposed(true),
m_windowState(Qt::WindowNoState) m_windowState(Qt::WindowNoState),
m_mmRendererWindow(0)
{ {
qWindowDebug() << Q_FUNC_INFO << "window =" << window << ", size =" << window->size(); qWindowDebug() << Q_FUNC_INFO << "window =" << window << ", size =" << window->size();
int result; int result;
@ -489,6 +490,22 @@ void QQnxWindow::gainedFocus()
QWindowSystemInterface::handleWindowActivated(window()); QWindowSystemInterface::handleWindowActivated(window());
} }
void QQnxWindow::setMMRendererWindowName(const QString &name)
{
m_mmRendererWindowName = name;
}
void QQnxWindow::setMMRendererWindow(screen_window_t handle)
{
m_mmRendererWindow = handle;
}
void QQnxWindow::clearMMRendererWindow()
{
m_mmRendererWindowName.clear();
m_mmRendererWindow = 0;
}
QQnxWindow *QQnxWindow::findWindow(screen_window_t windowHandle) QQnxWindow *QQnxWindow::findWindow(screen_window_t windowHandle)
{ {
if (m_window == windowHandle) if (m_window == windowHandle)
@ -583,17 +600,25 @@ void QQnxWindow::initWindow()
void QQnxWindow::updateZorder(int &topZorder) void QQnxWindow::updateZorder(int &topZorder)
{ {
errno = 0; updateZorder(m_window, topZorder);
int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ZORDER, &topZorder);
topZorder++;
if (result != 0) if (m_mmRendererWindow)
qFatal("QQnxWindow: failed to set window z-order=%d, errno=%d, mWindow=%p", topZorder, errno, m_window); updateZorder(m_mmRendererWindow, topZorder);
Q_FOREACH (QQnxWindow *childWindow, m_childWindows) Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->updateZorder(topZorder); childWindow->updateZorder(topZorder);
} }
void QQnxWindow::updateZorder(screen_window_t window, int &topZorder)
{
errno = 0;
int result = screen_set_window_property_iv(window, SCREEN_PROPERTY_ZORDER, &topZorder);
topZorder++;
if (result != 0)
qFatal("QQnxWindow: failed to set window z-order=%d, errno=%d, mWindow=%p", topZorder, errno, window);
}
void QQnxWindow::applyWindowState() void QQnxWindow::applyWindowState()
{ {
switch (m_windowState) { switch (m_windowState) {

View File

@ -99,6 +99,9 @@ public:
void propagateSizeHints(); void propagateSizeHints();
void gainedFocus(); void gainedFocus();
void setMMRendererWindowName(const QString &name);
void setMMRendererWindow(screen_window_t handle);
void clearMMRendererWindow();
QQnxScreen *screen() const { return m_screen; } QQnxScreen *screen() const { return m_screen; }
const QList<QQnxWindow*>& children() const { return m_childWindows; } const QList<QQnxWindow*>& children() const { return m_childWindows; }
@ -107,6 +110,10 @@ public:
void minimize(); void minimize();
QString mmRendererWindowName() const { return m_mmRendererWindowName; }
screen_window_t mmRendererWindow() const { return m_mmRendererWindow; }
virtual WindowType windowType() const = 0; virtual WindowType windowType() const = 0;
protected: protected:
virtual int pixelFormat() const = 0; virtual int pixelFormat() const = 0;
@ -123,6 +130,7 @@ private:
void setOffset(const QPoint &setOffset); void setOffset(const QPoint &setOffset);
void updateVisibility(bool parentVisible); void updateVisibility(bool parentVisible);
void updateZorder(int &topZorder); void updateZorder(int &topZorder);
void updateZorder(screen_window_t window, int &zOrder);
void applyWindowState(); void applyWindowState();
screen_window_t m_window; screen_window_t m_window;
@ -135,6 +143,8 @@ private:
bool m_exposed; bool m_exposed;
QRect m_unmaximizedGeometry; QRect m_unmaximizedGeometry;
Qt::WindowState m_windowState; Qt::WindowState m_windowState;
QString m_mmRendererWindowName;
screen_window_t m_mmRendererWindow;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE