summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-06-20 07:54:09 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2016-06-20 07:54:09 +0000
commit5f0ec7305e4310123ddeb98d3523087e3c560d9c (patch)
treefbcad900b0b604a1005320c5015723c343807974 /src/plugins
parent683c30074e4b7c9048e9970de1851e5d9a6deeb4 (diff)
parente32f1a4d61f0c55d066a43657ad607131be8ca34 (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.mm2
-rw-r--r--src/plugins/generic/tuiotouch/qtuiohandler.cpp1
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp12
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.h7
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.mm134
-rw-r--r--src/plugins/platforms/ios/qioscontext.h5
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm159
-rw-r--r--src/plugins/platforms/ios/qiosscreen.h5
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm58
-rw-r--r--src/plugins/platforms/ios/qioswindow.h4
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm11
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri2
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro2
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