diff options
author | Liang Qi <liang.qi@qt.io> | 2016-06-20 07:54:09 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2016-06-20 07:54:09 +0000 |
commit | 5f0ec7305e4310123ddeb98d3523087e3c560d9c (patch) | |
tree | fbcad900b0b604a1005320c5015723c343807974 /src/plugins | |
parent | 683c30074e4b7c9048e9970de1851e5d9a6deeb4 (diff) | |
parent | e32f1a4d61f0c55d066a43657ad607131be8ca34 (diff) |
Merge "Merge remote-tracking branch 'origin/5.6' into 5.7" into refs/staging/5.7
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/bearer/corewlan/qcorewlanengine.mm | 2 | ||||
-rw-r--r-- | src/plugins/generic/tuiotouch/qtuiohandler.cpp | 1 | ||||
-rw-r--r-- | src/plugins/platforms/android/androidjniinput.cpp | 12 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosapplicationstate.h | 7 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosapplicationstate.mm | 134 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioscontext.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioscontext.mm | 159 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosscreen.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosscreen.mm | 58 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioswindow.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioswindow.mm | 11 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/xcb_qpa_lib.pro | 2 |
13 files changed, 236 insertions, 166 deletions
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 3f8f80fc85..52e76219e6 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -85,7 +85,7 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time [locker lock]; QMacAutoReleasePool pool; notificationCenter = [NSNotificationCenter defaultCenter]; - currentInterface = [CWInterface interfaceWithName:nil]; + currentInterface = [CWInterface interface]; [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:CWPowerDidChangeNotification object:nil]; [locker unlock]; return self; diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp index 6026e06b55..5d34e0ea38 100644 --- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp +++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp @@ -306,7 +306,6 @@ QWindowSystemInterface::TouchPoint QTuioHandler::cursorToTouchPoint(const QTuioC tp.normalPosition = m_transform.map(tp.normalPosition); tp.state = tc.state(); - tp.area = QRectF(0, 0, 1, 1); // we map the touch to the size of the window. we do this, because frankly, // trying to figure out which part of the screen to hit in order to press an diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 064a0c095c..5be128a0c5 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -252,9 +252,19 @@ namespace QtAndroidInput QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints); } + static bool isTabletEventSupported(JNIEnv */*env*/, jobject /*thiz*/) + { +#ifdef QT_NO_TABLETEVENT + return false; +#else + return true; +#endif // QT_NO_TABLETEVENT + } + static void tabletEvent(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint deviceId, jlong time, jint action, jint pointerType, jint buttonState, jfloat x, jfloat y, jfloat pressure) { +#ifndef QT_NO_TABLETEVENT QPointF globalPosF(x, y); QPoint globalPos((int)x, (int)y); QWindow *tlw = topLevelWindowAt(globalPos); @@ -296,6 +306,7 @@ namespace QtAndroidInput QWindowSystemInterface::handleTabletEvent(tlw, ulong(time), localPos, globalPosF, QTabletEvent::Stylus, pointerType, buttons, pressure, 0, 0, 0., 0., 0, deviceId, Qt::NoModifier); +#endif // QT_NO_TABLETEVENT } static int mapAndroidKey(int key) @@ -783,6 +794,7 @@ namespace QtAndroidInput {"mouseUp", "(III)V", (void *)mouseUp}, {"mouseMove", "(III)V", (void *)mouseMove}, {"longPress", "(III)V", (void *)longPress}, + {"isTabletEventSupported", "()Z", (void *)isTabletEventSupported}, {"tabletEvent", "(IIJIIIFFF)V", (void *)tabletEvent}, {"keyDown", "(IIIZ)V", (void *)keyDown}, {"keyUp", "(IIIZ)V", (void *)keyUp}, diff --git a/src/plugins/platforms/ios/qiosapplicationstate.h b/src/plugins/platforms/ios/qiosapplicationstate.h index e487407d7b..1c77b26da1 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.h +++ b/src/plugins/platforms/ios/qiosapplicationstate.h @@ -41,10 +41,11 @@ #define QIOSAPPLICATIONSTATE_H #include <QtCore/qglobal.h> +#include <QtCore/qvector.h> -QT_BEGIN_NAMESPACE +Q_FORWARD_DECLARE_OBJC_CLASS(NSObject); -@class QIOSApplicationStateListener; +QT_BEGIN_NAMESPACE class QIOSApplicationState { @@ -52,7 +53,7 @@ public: QIOSApplicationState(); ~QIOSApplicationState(); private: - QIOSApplicationStateListener *m_listener; + QVector<NSObject*> m_observers; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index afb61a134b..7b923e4692 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -42,100 +42,21 @@ #include <qpa/qwindowsysteminterface.h> #include <QtCore/qcoreapplication.h> -#import <UIKit/UIKit.h> - -@interface QIOSApplicationStateListener : NSObject -@end +#include <QtGui/private/qguiapplication_p.h> -@implementation QIOSApplicationStateListener - -- (id)init -{ - self = [super init]; - if (self) { - // Listen for application state changes. - // Note: We use notifications rather than application delegate callbacks to - // also support hybrid applications were QIOSApplicationDelegate is not in use. - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(applicationDidBecomeActive) - name:UIApplicationDidBecomeActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(applicationWillResignActive) - name:UIApplicationWillResignActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(applicationDidEnterBackground) - name:UIApplicationDidEnterBackgroundNotification - object:nil]; - - // Update the current state now, since we have missed all the updates - // posted from AppKit so far. But let QPA finish initialization first. - dispatch_async(dispatch_get_main_queue(), ^{ - [self handleApplicationStateChanged:[UIApplication sharedApplication].applicationState]; - }); - } - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] - removeObserver:self - name:UIApplicationDidBecomeActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - removeObserver:self - name:UIApplicationWillResignActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - removeObserver:self - name:UIApplicationDidEnterBackgroundNotification - object:nil]; - [super dealloc]; -} - -- (void)applicationDidBecomeActive -{ - [self handleApplicationStateChanged:UIApplicationStateActive]; -} - -- (void)applicationWillResignActive -{ - // Note that UIApplication is still UIApplicationStateActive at this - // point, but since there is no separate notification for the inactive - // state, we report UIApplicationStateInactive now: - [self handleApplicationStateChanged:UIApplicationStateInactive]; -} - -- (void)applicationDidEnterBackground -{ - [self handleApplicationStateChanged:UIApplicationStateBackground]; -} +#import <UIKit/UIKit.h> -- (void)handleApplicationStateChanged:(UIApplicationState)uiApplicationState +static Qt::ApplicationState qtApplicationState(UIApplicationState uiApplicationState) { - // We may receive application state changes after QCoreApplication has - // gone down, as the block we schedule on the main queue keeps the - // listener alive. In that case we just ignore the notification. - if (!qApp) - return; - - Qt::ApplicationState state; switch (uiApplicationState) { case UIApplicationStateActive: - // The application is visible in front, and receiving events: - state = Qt::ApplicationActive; - break; + // The application is visible in front, and receiving events + return Qt::ApplicationActive; case UIApplicationStateInactive: // The app is running in the foreground but is not receiving events. This // typically happens while transitioning to/from active/background, like - // upon app launch or when receiving incoming calls: - state = Qt::ApplicationInactive; - break; + // upon app launch or when receiving incoming calls. + return Qt::ApplicationInactive; case UIApplicationStateBackground: // Normally the app would enter this state briefly before it gets // suspeded (you have five seconds, according to Apple). @@ -144,25 +65,54 @@ // API for doing that yet, we handle this state as "about to be suspended". // Note: A screen-shot for the SpringBoard will also be taken after this // call returns. - state = Qt::ApplicationSuspended; - break; + return Qt::ApplicationSuspended; } +} + +static void handleApplicationStateChanged(UIApplicationState uiApplicationState) +{ + Qt::ApplicationState state = qtApplicationState(uiApplicationState); QWindowSystemInterface::handleApplicationStateChanged(state); QWindowSystemInterface::flushWindowSystemEvents(); } -@end - QT_BEGIN_NAMESPACE QIOSApplicationState::QIOSApplicationState() - : m_listener([[QIOSApplicationStateListener alloc] init]) { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + + m_observers.push_back([notificationCenter addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { + handleApplicationStateChanged(UIApplicationStateActive); + } + ]); + + m_observers.push_back([notificationCenter addObserverForName:UIApplicationWillResignActiveNotification + object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { + // Note: UIApplication is still UIApplicationStateActive at this point, + // but since there is no separate notification for the inactive state, + // we report UIApplicationStateInactive now. + handleApplicationStateChanged(UIApplicationStateInactive); + } + ]); + + m_observers.push_back([notificationCenter addObserverForName:UIApplicationDidEnterBackgroundNotification + object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { + handleApplicationStateChanged(UIApplicationStateBackground); + } + ]); + + // Initialize correct startup state, which may not be the Qt default (inactive) + UIApplicationState startupState = [UIApplication sharedApplication].applicationState; + QGuiApplicationPrivate::applicationState = qtApplicationState(startupState); } QIOSApplicationState::~QIOSApplicationState() { - [m_listener release]; + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + foreach (const NSObject* observer, m_observers) + [notificationCenter removeObserver:observer]; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h index c8a4fae20c..5b7917f7b4 100644 --- a/src/plugins/platforms/ios/qioscontext.h +++ b/src/plugins/platforms/ios/qioscontext.h @@ -40,6 +40,7 @@ #ifndef QIOSCONTEXT_H #define QIOSCONTEXT_H +#include <QtCore/qloggingcategory.h> #include <qpa/qplatformopenglcontext.h> @class EAGLContext; @@ -89,7 +90,9 @@ private: static void deleteBuffers(const FramebufferObject &framebufferObject); FramebufferObject &backingFramebufferObjectFor(QPlatformSurface *) const; - mutable QHash<QIOSWindow *, FramebufferObject> m_framebufferObjects; + mutable QHash<QPlatformSurface *, FramebufferObject> m_framebufferObjects; + + bool needsRenderbufferResize(QPlatformSurface *) const; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 546b003d14..d18e317bfb 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -48,6 +48,8 @@ #import <OpenGLES/ES2/glext.h> #import <QuartzCore/CAEAGLLayer.h> +Q_LOGGING_CATEGORY(lcQpaGLContext, "qt.qpa.glcontext"); + QIOSContext::QIOSContext(QOpenGLContext *context) : QPlatformOpenGLContext() , m_sharedContext(static_cast<QIOSContext *>(context->shareHandle())) @@ -81,6 +83,8 @@ QIOSContext::QIOSContext(QOpenGLContext *context) // could take advantage of the unchanged buffer, but this means clients (and Qt) // will also assume that swapBufferes() is not needed, which is _not_ the case. m_format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + + qCDebug(lcQpaGLContext) << "created context with format" << m_format << "shared with" << m_sharedContext; } QIOSContext::~QIOSContext() @@ -123,10 +127,12 @@ static QString fboStatusString(GLenum status) } } +#define Q_ASSERT_IS_GL_SURFACE(surface) \ + Q_ASSERT(surface && (surface->surface()->surfaceType() & (QSurface::OpenGLSurface | QSurface::RasterGLSurface))) + bool QIOSContext::makeCurrent(QPlatformSurface *surface) { - Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface - || surface->surface()->surfaceType() == QSurface::RasterGLSurface)); + Q_ASSERT_IS_GL_SURFACE(surface); [EAGLContext setCurrentContext:m_eaglContext]; @@ -134,54 +140,11 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface) if (surface->surface()->surfaceClass() == QSurface::Offscreen) return true; + Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window); FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); - // We bind the default FBO even if it's incomplete, so that clients who - // call glCheckFramebufferStatus as a result of this function returning - // false will get a matching error code. - glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); - - return framebufferObject.isComplete; -} - -void QIOSContext::doneCurrent() -{ - [EAGLContext setCurrentContext:nil]; -} - -void QIOSContext::swapBuffers(QPlatformSurface *surface) -{ - Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface - || surface->surface()->surfaceType() == QSurface::RasterGLSurface)); - - if (surface->surface()->surfaceClass() == QSurface::Offscreen) - return; // Nothing to do - - FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); - - [EAGLContext setCurrentContext:m_eaglContext]; - glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer); - [m_eaglContext presentRenderbuffer:GL_RENDERBUFFER]; -} - -QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatformSurface *surface) const -{ - // We keep track of default-FBOs in the root context of a share-group. This assumes - // that the contexts form a tree, where leaf nodes are always destroyed before their - // parents. If that assumption (based on the current implementation) doesn't hold we - // should probably use QOpenGLMultiGroupSharedResource to track the shared default-FBOs. - if (m_sharedContext) - return m_sharedContext->backingFramebufferObjectFor(surface); - - Q_ASSERT(surface && surface->surface()->surfaceClass() == QSurface::Window); - QIOSWindow *window = static_cast<QIOSWindow *>(surface); - - FramebufferObject &framebufferObject = m_framebufferObjects[window]; - - // Set up an FBO for the window if it hasn't been created yet if (!framebufferObject.handle) { - [EAGLContext setCurrentContext:m_eaglContext]; - + // Set up an FBO for the window if it hasn't been created yet glGenFramebuffers(1, &framebufferObject.handle); glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); @@ -201,17 +164,17 @@ QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatfo framebufferObject.depthRenderbuffer); } - connect(window, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*))); + connect(static_cast<QIOSWindow *>(surface), SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*))); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); } - // Ensure that the FBO's buffers match the size of the layer - UIView *view = reinterpret_cast<UIView *>(window->winId()); - CAEAGLLayer *layer = static_cast<CAEAGLLayer *>(view.layer); - if (framebufferObject.renderbufferWidth != (layer.frame.size.width * layer.contentsScale) || - framebufferObject.renderbufferHeight != (layer.frame.size.height * layer.contentsScale)) { - - [EAGLContext setCurrentContext:m_eaglContext]; - glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); + if (needsRenderbufferResize(surface)) { + // Ensure that the FBO's buffers match the size of the layer + CAEAGLLayer *layer = static_cast<QIOSWindow *>(surface)->eaglLayer(); + qCDebug(lcQpaGLContext, "Reallocating renderbuffer storage - current: %dx%d, layer: %gx%g", + framebufferObject.renderbufferWidth, framebufferObject.renderbufferHeight, + layer.frame.size.width * layer.contentsScale, layer.frame.size.height * layer.contentsScale); glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer); [m_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]; @@ -234,12 +197,54 @@ QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatfo framebufferObject.isComplete = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE; if (!framebufferObject.isComplete) { - qWarning("QIOSContext failed to make complete framebuffer object (%s)", + qCWarning(lcQpaGLContext, "QIOSContext failed to make complete framebuffer object (%s)", qPrintable(fboStatusString(glCheckFramebufferStatus(GL_FRAMEBUFFER)))); } } - return framebufferObject; + return framebufferObject.isComplete; +} + +void QIOSContext::doneCurrent() +{ + [EAGLContext setCurrentContext:nil]; +} + +void QIOSContext::swapBuffers(QPlatformSurface *surface) +{ + Q_ASSERT_IS_GL_SURFACE(surface); + + if (surface->surface()->surfaceClass() == QSurface::Offscreen) + return; // Nothing to do + + if (!static_cast<QIOSWindow *>(surface)->isExposed()) { + qCWarning(lcQpaGLContext, "Detected swapBuffers on a non-exposed window, skipping flush"); + return; + } + + FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); + Q_ASSERT_X(framebufferObject.isComplete, "QIOSContext", "swapBuffers on incomplete FBO"); + + if (needsRenderbufferResize(surface)) { + qCWarning(lcQpaGLContext, "CAEAGLLayer was resized between makeCurrent and swapBuffers, skipping flush"); + return; + } + + [EAGLContext setCurrentContext:m_eaglContext]; + glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer); + [m_eaglContext presentRenderbuffer:GL_RENDERBUFFER]; +} + +QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatformSurface *surface) const +{ + // We keep track of default-FBOs in the root context of a share-group. This assumes + // that the contexts form a tree, where leaf nodes are always destroyed before their + // parents. If that assumption (based on the current implementation) doesn't hold we + // should probably use QOpenGLMultiGroupSharedResource to track the shared default-FBOs. + if (m_sharedContext) + return m_sharedContext->backingFramebufferObjectFor(surface); + else + return m_framebufferObjects[surface]; } GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const @@ -251,19 +256,41 @@ GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const return 0; } - return backingFramebufferObjectFor(surface).handle; + FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); + Q_ASSERT_X(framebufferObject.handle, "QIOSContext", "can't resolve default FBO before makeCurrent"); + + return framebufferObject.handle; +} + +bool QIOSContext::needsRenderbufferResize(QPlatformSurface *surface) const +{ + Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window); + + FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); + CAEAGLLayer *layer = static_cast<QIOSWindow *>(surface)->eaglLayer(); + + if (framebufferObject.renderbufferWidth != (layer.frame.size.width * layer.contentsScale)) + return true; + + if (framebufferObject.renderbufferHeight != (layer.frame.size.height * layer.contentsScale)) + return true; + + return false; } void QIOSContext::windowDestroyed(QObject *object) { QIOSWindow *window = static_cast<QIOSWindow *>(object); - if (m_framebufferObjects.contains(window)) { - EAGLContext *originalContext = [EAGLContext currentContext]; - [EAGLContext setCurrentContext:m_eaglContext]; - deleteBuffers(m_framebufferObjects[window]); - m_framebufferObjects.remove(window); - [EAGLContext setCurrentContext:originalContext]; - } + if (!m_framebufferObjects.contains(window)) + return; + + qCDebug(lcQpaGLContext) << object << "destroyed, deleting corresponding FBO"; + + EAGLContext *originalContext = [EAGLContext currentContext]; + [EAGLContext setCurrentContext:m_eaglContext]; + deleteBuffers(m_framebufferObjects[window]); + m_framebufferObjects.remove(window); + [EAGLContext setCurrentContext:originalContext]; } QFunctionPointer QIOSContext::getProcAddress(const char *functionName) diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index 56a0874bb4..cc83e7f3d2 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -71,9 +71,13 @@ public: UIScreen *uiScreen() const; UIWindow *uiWindow() const; + void setUpdatesPaused(bool); + void updateProperties(); private: + void deliverUpdateRequests() const; + UIScreen *m_uiScreen; UIWindow *m_uiWindow; QRect m_geometry; @@ -82,6 +86,7 @@ private: uint m_physicalDpi; QSizeF m_physicalSize; QIOSOrientationListener *m_orientationListener; + CADisplayLink *m_displayLink; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index bfd22abaa4..d53f0df846 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -46,10 +46,33 @@ #include "qiosviewcontroller.h" #include "quiview.h" +#include <QtGui/private/qwindow_p.h> + #include <sys/sysctl.h> // ------------------------------------------------------------------------- +typedef void (^DisplayLinkBlock)(CADisplayLink *displayLink); + +@implementation UIScreen (DisplayLinkBlock) +- (CADisplayLink*)displayLinkWithBlock:(DisplayLinkBlock)block +{ + return [self displayLinkWithTarget:[[block copy] autorelease] + selector:@selector(invokeDisplayLinkBlock:)]; +} +@end + +@implementation NSObject (DisplayLinkBlock) +- (void)invokeDisplayLinkBlock:(CADisplayLink *)sender +{ + DisplayLinkBlock block = static_cast<id>(self); + block(sender); +} +@end + + +// ------------------------------------------------------------------------- + static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) { foreach (QScreen *screen, QGuiApplication::screens()) { @@ -214,10 +237,16 @@ QIOSScreen::QIOSScreen(UIScreen *screen) } updateProperties(); + + m_displayLink = [m_uiScreen displayLinkWithBlock:^(CADisplayLink *) { deliverUpdateRequests(); }]; + m_displayLink.paused = YES; // Enabled when clients call QWindow::requestUpdate() + [m_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } QIOSScreen::~QIOSScreen() { + [m_displayLink invalidate]; + [m_orientationListener release]; [m_uiWindow release]; } @@ -297,6 +326,35 @@ void QIOSScreen::updateProperties() QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry, m_availableGeometry); } +void QIOSScreen::setUpdatesPaused(bool paused) +{ + m_displayLink.paused = paused; +} + +void QIOSScreen::deliverUpdateRequests() const +{ + bool pauseUpdates = true; + + QList<QWindow*> windows = QGuiApplication::allWindows(); + for (int i = 0; i < windows.size(); ++i) { + if (platformScreenForWindow(windows.at(i)) != this) + continue; + + QWindowPrivate *wp = static_cast<QWindowPrivate *>(QObjectPrivate::get(windows.at(i))); + if (!wp->updateRequestPending) + continue; + + wp->deliverUpdateRequest(); + + // Another update request was triggered, keep the display link running + if (wp->updateRequestPending) + pauseUpdates = false; + } + + // Pause the display link if there are no pending update requests + m_displayLink.paused = pauseUpdates; +} + QRect QIOSScreen::geometry() const { return m_geometry; diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index 6005d6dae3..afc2f0f89d 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -88,6 +88,10 @@ public: QSurfaceFormat format() const Q_DECL_OVERRIDE; + void requestUpdate() Q_DECL_OVERRIDE; + + CAEAGLLayer *eaglLayer() const; + private: void applicationStateChanged(Qt::ApplicationState state); void applyGeometry(const QRect &rect); diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 481d4a06ab..fb2fd2b946 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -377,6 +377,17 @@ void QIOSWindow::clearAccessibleCache() [m_view clearAccessibleCache]; } +void QIOSWindow::requestUpdate() +{ + static_cast<QIOSScreen *>(screen())->setUpdatesPaused(false); +} + +CAEAGLLayer *QIOSWindow::eaglLayer() const +{ + Q_ASSERT([m_view.layer isKindOfClass:[CAEAGLLayer class]]); + return static_cast<CAEAGLLayer *>(m_view.layer); +} + #include "moc_qioswindow.cpp" QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri index e859865687..c2d3849d8e 100644 --- a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri @@ -31,7 +31,7 @@ contains(QT_CONFIG, xcb-qt) { DEFINES += XCB_USE_RENDER XCB_DIR = $$clean_path($$PWD/../../../../3rdparty/xcb) INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude - LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static + LIBS += -lxcb -L$$MODULE_BASE_OUTDIR/lib -lxcb-static$$qtPlatformTargetSuffix() } else { LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms !contains(DEFINES, QT_NO_XKB):LIBS += -lxcb-xkb diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index f4a4e5a78a..db9ea32cd8 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -88,7 +88,7 @@ contains(QT_CONFIG, xcb-qt) { DEFINES += XCB_USE_RENDER XCB_DIR = ../../../3rdparty/xcb INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude - LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static + LIBS += -lxcb -L$$MODULE_BASE_OUTDIR/lib -lxcb-static$$qtPlatformTargetSuffix() } else { LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms -lxcb-xinerama !contains(DEFINES, QT_NO_XKB):LIBS += -lxcb-xkb |