diff options
author | Thomas McGuire <thomas.mcguire@kdab.com> | 2012-03-27 15:22:25 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-04-03 13:08:41 (GMT) |
commit | 45c6fc890c226c9021d41373c7718d596eb888d1 (patch) | |
tree | 9fce51d647454495c1c01ff8603ea0da9d64db4c /src | |
parent | dcacb8833a92bf6f28a9f709fb6b88a733ba2101 (diff) | |
download | Qt-45c6fc890c226c9021d41373c7718d596eb888d1.zip Qt-45c6fc890c226c9021d41373c7718d596eb888d1.tar.gz Qt-45c6fc890c226c9021d41373c7718d596eb888d1.tar.bz2 |
Add support for screen overlays / foreign windows
We're not the only one creating native windows. When using the
multimedia API, the multimedia library creates a video window
for video display. Here we need to deal with giving this video
window overlay a proper z-order, otherwise it will never get
visible.
Cherry-picked from qtbase 4efd61c3cf3d25db1c60bf5c842837c5b24a05fa
Change-Id: If2e2a6e51ae6553fdf645e578f68e41c7b43336a
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com>
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
Diffstat (limited to 'src')
8 files changed, 112 insertions, 19 deletions
diff --git a/src/plugins/platforms/blackberry/qbbeventthread.cpp b/src/plugins/platforms/blackberry/qbbeventthread.cpp index ae3d44d..2593223 100644 --- a/src/plugins/platforms/blackberry/qbbeventthread.cpp +++ b/src/plugins/platforms/blackberry/qbbeventthread.cpp @@ -48,9 +48,10 @@ QT_BEGIN_NAMESPACE -QBBEventThread::QBBEventThread(screen_context_t context) +QBBEventThread::QBBEventThread(screen_context_t context, QBBScreenEventHandler *eventHandler) : mContext(context), - mQuit(false) + mQuit(false), + mEventHandler(eventHandler) { } @@ -67,7 +68,7 @@ void QBBEventThread::injectKeyboardEvent(int flags, int sym, int mod, int scan, void QBBEventThread::injectPointerMoveEvent(int x, int y) { - mEventHandler.injectPointerMoveEvent(x, y); + mEventHandler->injectPointerMoveEvent(x, y); } void QBBEventThread::run() @@ -107,7 +108,7 @@ void QBBEventThread::run() #endif mQuit = true; } else { - mEventHandler.handleEvent(event, qnxType); + mEventHandler->handleEvent(event, qnxType); } } diff --git a/src/plugins/platforms/blackberry/qbbeventthread.h b/src/plugins/platforms/blackberry/qbbeventthread.h index 23bb249..df8c0ea 100644 --- a/src/plugins/platforms/blackberry/qbbeventthread.h +++ b/src/plugins/platforms/blackberry/qbbeventthread.h @@ -40,18 +40,18 @@ #ifndef QBBEVENTTHREAD_H #define QBBEVENTTHREAD_H -#include "qbbscreeneventhandler.h" - #include <QThread> #include <screen/screen.h> QT_BEGIN_NAMESPACE +class QBBScreenEventHandler; + class QBBEventThread : public QThread { public: - explicit QBBEventThread(screen_context_t context); + QBBEventThread(screen_context_t context, QBBScreenEventHandler *eventHandler); virtual ~QBBEventThread(); static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap); @@ -63,7 +63,7 @@ protected: private: screen_context_t mContext; bool mQuit; - QBBScreenEventHandler mEventHandler; + QBBScreenEventHandler *mEventHandler; void shutdown(); }; diff --git a/src/plugins/platforms/blackberry/qbbintegration.cpp b/src/plugins/platforms/blackberry/qbbintegration.cpp index 840ae1f..5ca3833 100644 --- a/src/plugins/platforms/blackberry/qbbintegration.cpp +++ b/src/plugins/platforms/blackberry/qbbintegration.cpp @@ -47,6 +47,7 @@ #include "qbbnavigatoreventhandler.h" #include "qbbrasterwindowsurface.h" #include "qbbscreen.h" +#include "qbbscreeneventhandler.h" #include "qbbwindow.h" #include "qbbvirtualkeyboard.h" #include "qgenericunixfontdatabase.h" @@ -69,11 +70,16 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_METATYPE(screen_window_t); + QBBIntegration::QBBIntegration() : mFontDb(new QGenericUnixFontDatabase()), + mScreenEventHandler(new QBBScreenEventHandler()), mPaintUsingOpenGL(getenv("QBB_USE_OPENGL") != NULL), mVirtualKeyboard(0) { + qRegisterMetaType<screen_window_t>(); + if (mPaintUsingOpenGL) { // Set default window API to OpenGL QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); @@ -95,7 +101,7 @@ QBBIntegration::QBBIntegration() : createDisplays(); // create/start event thread - mEventThread = new QBBEventThread(mContext); + mEventThread = new QBBEventThread(mContext, mScreenEventHandler); mEventThread->start(); // Create/start navigator event handler @@ -138,6 +144,8 @@ QBBIntegration::~QBBIntegration() #if defined(QBBINTEGRATION_DEBUG) qDebug() << "QBB: platform plugin shutdown begin"; #endif + + // destroy the keyboard class. delete mVirtualKeyboard; @@ -152,6 +160,8 @@ QBBIntegration::~QBBIntegration() // stop/destroy navigator thread delete mNavigatorEventHandler; + delete mScreenEventHandler; + // destroy all displays destroyDisplays(); @@ -271,6 +281,11 @@ void QBBIntegration::createDisplays() #endif QBBScreen *screen = new QBBScreen(mContext, displays[i], i); mScreens.push_back(screen); + + QObject::connect(mScreenEventHandler, SIGNAL(newWindowCreated(screen_window_t)), + screen, SLOT(newWindowCreated(screen_window_t))); + QObject::connect(mScreenEventHandler, SIGNAL(windowClosed(screen_window_t)), + screen, SLOT(windowClosed(screen_window_t))); } } diff --git a/src/plugins/platforms/blackberry/qbbintegration.h b/src/plugins/platforms/blackberry/qbbintegration.h index 355008c..2d81184 100644 --- a/src/plugins/platforms/blackberry/qbbintegration.h +++ b/src/plugins/platforms/blackberry/qbbintegration.h @@ -51,6 +51,7 @@ class QBBNavigatorEventHandler; class QBBLocaleThread; class QBBAbstractVirtualKeyboard; class QBBScreen; +class QBBScreenEventHandler; class QBBIntegration : public QPlatformIntegration { @@ -87,6 +88,7 @@ private: QBBLocaleThread *mLocaleThread; QPlatformFontDatabase *mFontDb; QList<QPlatformScreen*> mScreens; + QBBScreenEventHandler *mScreenEventHandler; bool mPaintUsingOpenGL; QBBAbstractVirtualKeyboard *mVirtualKeyboard; }; diff --git a/src/plugins/platforms/blackberry/qbbscreen.cpp b/src/plugins/platforms/blackberry/qbbscreen.cpp index fd075d1..5c91979 100644 --- a/src/plugins/platforms/blackberry/qbbscreen.cpp +++ b/src/plugins/platforms/blackberry/qbbscreen.cpp @@ -44,6 +44,7 @@ #include "qbbwindow.h" #include <QDebug> +#include <QtCore/QThread> #include <QtGui/QWindowSystemInterface> #include <errno.h> @@ -135,6 +136,31 @@ void QBBScreen::ensureDisplayCreated() mRootWindow = QSharedPointer<QBBRootWindow>(new QBBRootWindow(this)); } +void QBBScreen::newWindowCreated(screen_window_t window) +{ + Q_ASSERT(thread() == QThread::currentThread()); + screen_display_t display = 0; + if (screen_get_window_property_pv(window, SCREEN_PROPERTY_DISPLAY, (void**)&display) != 0) { + qWarning("QBBScreen: Failed to get screen for window, errno=%d", errno); + return; + } + + if (display == nativeDisplay()) { + // 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 + // creates an overlay window when playing a video. + // Treat all foreign windows as overlays here. + if (!findWindow(window)) + addOverlayWindow(window); + } +} + +void QBBScreen::windowClosed(screen_window_t window) +{ + Q_ASSERT(thread() == QThread::currentThread()); + removeOverlayWindow(window); +} + QRect QBBScreen::availableGeometry() const { // available geometry = total geometry - keyboard @@ -269,6 +295,15 @@ void QBBScreen::updateHierarchy() (*it)->updateZorder(topZorder); } + topZorder++; + Q_FOREACH (screen_window_t overlay, mOverlays) { + // Do nothing when this fails. This can happen if we have stale windows in mOverlays, + // which in turn can happen because a window was removed but we didn't get a notification + // yet. + screen_set_window_property_iv(overlay, SCREEN_PROPERTY_ZORDER, &topZorder); + topZorder++; + } + // After a hierarchy update, we need to force a flush on all screens. // Right now, all screens share a context. screen_flush_context( mContext, 0 ); @@ -297,4 +332,17 @@ void QBBScreen::keyboardHeightChanged(int height) QWindowSystemInterface::handleScreenAvailableGeometryChange(mScreenIndex); } +void QBBScreen::addOverlayWindow(screen_window_t window) +{ + mOverlays.append(window); + updateHierarchy(); +} + +void QBBScreen::removeOverlayWindow(screen_window_t window) +{ + const int numOverlaysRemoved = mOverlays.removeAll(window); + if (numOverlaysRemoved > 0) + updateHierarchy(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/blackberry/qbbscreen.h b/src/plugins/platforms/blackberry/qbbscreen.h index 0f8f839..22d210a 100644 --- a/src/plugins/platforms/blackberry/qbbscreen.h +++ b/src/plugins/platforms/blackberry/qbbscreen.h @@ -85,10 +85,17 @@ public: QSharedPointer<QBBRootWindow> rootWindow() const { return mRootWindow; } +public Q_SLOTS: + void newWindowCreated(screen_window_t window); + void windowClosed(screen_window_t window); + private Q_SLOTS: void keyboardHeightChanged(int height); private: + void addOverlayWindow(screen_window_t window); + void removeOverlayWindow(screen_window_t window); + screen_context_t mContext; screen_display_t mDisplay; QSharedPointer<QBBRootWindow> mRootWindow; @@ -105,6 +112,7 @@ private: QRect mCurrentGeometry; QList<QBBWindow*> mChildren; + QList<screen_window_t> mOverlays; int mScreenIndex; bool isPrimaryDisplay() { return mPrimaryDisplay; } diff --git a/src/plugins/platforms/blackberry/qbbscreeneventhandler.cpp b/src/plugins/platforms/blackberry/qbbscreeneventhandler.cpp index 567d572..1a87c7e 100644 --- a/src/plugins/platforms/blackberry/qbbscreeneventhandler.cpp +++ b/src/plugins/platforms/blackberry/qbbscreeneventhandler.cpp @@ -105,6 +105,10 @@ bool QBBScreenEventHandler::handleEvent(screen_event_t event, int qnxType) handleCloseEvent(event); break; + case SCREEN_EVENT_CREATE: + handleCreateEvent(event); + break; + default: // event ignored #if defined(QBBEVENTTHREAD_DEBUG) @@ -511,18 +515,27 @@ void QBBScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType) void QBBScreenEventHandler::handleCloseEvent(screen_event_t event) { - // Query the window that was closed - void *qnxWindow; - int result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &qnxWindow); - if (result != 0) { - qFatal("QBB: failed to query event window, errno=%d", errno); - } + screen_window_t window = 0; + if (screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) + qFatal("QBB: failed to query event window property, errno=%d", errno); + + emit windowClosed(window); // map window to top-level widget - QWidget* w = QWidget::find( (WId)qnxWindow ); - if (w != NULL) { + QWidget* w = QWidget::find( (WId)window ); + if (w != NULL) QWindowSystemInterface::handleCloseEvent(w); - } } +void QBBScreenEventHandler::handleCreateEvent(screen_event_t event) +{ + screen_window_t window = 0; + if (screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) + qFatal("QBB: failed to query event window property, errno=%d", errno); + + emit newWindowCreated(window); +} + +#include "moc_qbbscreeneventhandler.cpp" + QT_END_NAMESPACE diff --git a/src/plugins/platforms/blackberry/qbbscreeneventhandler.h b/src/plugins/platforms/blackberry/qbbscreeneventhandler.h index 2e5851e..d6c253d 100644 --- a/src/plugins/platforms/blackberry/qbbscreeneventhandler.h +++ b/src/plugins/platforms/blackberry/qbbscreeneventhandler.h @@ -46,8 +46,9 @@ QT_BEGIN_NAMESPACE -class QBBScreenEventHandler +class QBBScreenEventHandler : public QObject { + Q_OBJECT public: QBBScreenEventHandler(); @@ -57,11 +58,16 @@ public: bool handleEvent(screen_event_t event); bool handleEvent(screen_event_t event, int qnxType); +Q_SIGNALS: + void newWindowCreated(screen_window_t window); + void windowClosed(screen_window_t window); + private: void handleKeyboardEvent(screen_event_t event); void handlePointerEvent(screen_event_t event); void handleTouchEvent(screen_event_t event, int type); void handleCloseEvent(screen_event_t event); + void handleCreateEvent(screen_event_t event); private: enum { |