summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-26 10:51:33 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-26 10:51:34 +0100
commit3061dc4abdfbd1a536918935d380872de6655521 (patch)
treeff440ed0c7d5816cc7e2874f73fdabfb0bce493f /src/plugins
parent25b2b682d616dd52c3515f443e3d25fc0224f3a2 (diff)
parent9b8570c4e9359eb8b45b39c28aa9d8c140f3fc44 (diff)
Merge remote-tracking branch 'origin/release' into stable
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/android/src/androidjnimain.cpp3
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformintegration.cpp9
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformintegration.h1
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformtheme.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm6
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.mm19
-rw-r--r--src/plugins/platforms/ios/qiosbackingstore.mm10
-rw-r--r--src/plugins/platforms/ios/qiosglobal.h9
-rw-r--r--src/plugins/platforms/ios/qiosglobal.mm12
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.h9
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm156
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm2
-rw-r--r--src/plugins/platforms/ios/qiosscreen.h8
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm67
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h1
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm35
-rw-r--r--src/plugins/platforms/ios/qioswindow.h6
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm231
-rw-r--r--src/plugins/platforms/qnx/qnx.pro6
-rw-r--r--src/plugins/platforms/qnx/qqnxeglwindow.cpp12
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp8
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp25
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp22
25 files changed, 576 insertions, 94 deletions
diff --git a/src/plugins/platforms/android/src/androidjnimain.cpp b/src/plugins/platforms/android/src/androidjnimain.cpp
index 3ab4eedb26..3064e5d4e2 100644
--- a/src/plugins/platforms/android/src/androidjnimain.cpp
+++ b/src/plugins/platforms/android/src/androidjnimain.cpp
@@ -40,6 +40,7 @@
**
****************************************************************************/
+#include <QtGui/private/qguiapplication_p.h>
#include <dlfcn.h>
#include <pthread.h>
@@ -691,7 +692,7 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state
{
m_activityActive = (state == Qt::ApplicationActive);
- if (!m_androidPlatformIntegration)
+ if (!m_androidPlatformIntegration || !QGuiApplicationPrivate::platformIntegration())
return;
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state));
diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
index 6d0ec306ab..ae3e257d3c 100644
--- a/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/src/qandroidplatformintegration.cpp
@@ -242,6 +242,15 @@ QVariant QAndroidPlatformIntegration::styleHint(StyleHint hint) const
}
}
+Qt::WindowState QAndroidPlatformIntegration::defaultWindowState(Qt::WindowFlags flags) const
+{
+ // Don't maximize dialogs on Android
+ if (flags & Qt::Dialog & ~Qt::Window)
+ return Qt::WindowNoState;
+
+ return QPlatformIntegration::defaultWindowState(flags);
+}
+
static const QLatin1String androidThemeName("android");
QStringList QAndroidPlatformIntegration::themeNames() const
{
diff --git a/src/plugins/platforms/android/src/qandroidplatformintegration.h b/src/plugins/platforms/android/src/qandroidplatformintegration.h
index 3b34cdf7df..bd08ad694c 100644
--- a/src/plugins/platforms/android/src/qandroidplatformintegration.h
+++ b/src/plugins/platforms/android/src/qandroidplatformintegration.h
@@ -121,6 +121,7 @@ public:
#endif
QVariant styleHint(StyleHint hint) const;
+ Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const Q_DECL_OVERRIDE;
QStringList themeNames() const;
QPlatformTheme *createPlatformTheme(const QString &name) const;
diff --git a/src/plugins/platforms/android/src/qandroidplatformtheme.cpp b/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
index 0ceac97e35..308bb70faf 100644
--- a/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
@@ -125,7 +125,7 @@ const QFont *QAndroidPlatformTheme::font(Font type) const
return &(it.value());
// default in case the style has not set a font
- static QFont systemFont("Roboto", 12.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi
+ static QFont systemFont("Roboto", 14.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi
if (type == QPlatformTheme::SystemFont)
return &systemFont;
return 0;
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm
index 0fea55ac68..5a8664747e 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm
@@ -175,6 +175,7 @@ void QCocoaMenuBar::handleReparent(QWindow *newParentWindow)
if (newParentWindow == NULL) {
m_window = NULL;
} else {
+ newParentWindow->create();
m_window = static_cast<QCocoaWindow*>(newParentWindow->handle());
m_window->setMenubar(this);
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index c22f254aef..4da47f4f1f 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -465,8 +465,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
{
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
NSInteger styleMask = NSBorderlessWindowMask;
+ if (flags & Qt::FramelessWindowHint)
+ return styleMask;
if ((type & Qt::Popup) == Qt::Popup) {
- if (!windowIsPopupType(type) && !(flags & Qt::FramelessWindowHint))
+ if (!windowIsPopupType(type))
styleMask = (NSUtilityWindowMask | NSResizableWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask | NSTitledWindowMask);
} else {
@@ -485,7 +487,7 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
} else {
styleMask = NSResizableWindowMask | NSClosableWindowMask | NSTitledWindowMask;
}
- } else if (!(flags & Qt::FramelessWindowHint)) {
+ } else {
if (flags & Qt::WindowMaximizeButtonHint)
styleMask |= NSResizableWindowMask;
if (flags & Qt::WindowTitleHint)
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
index 775074baae..cf702c82af 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
@@ -58,6 +58,25 @@
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.rootViewController = [[[QIOSViewController alloc] init] autorelease];
+#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_7_0)
+ QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion;
+
+ // We prefer to keep the root viewcontroller in fullscreen layout, so that
+ // we don't have to compensate for the viewcontroller position. This also
+ // gives us the same behavior on iOS 5/6 as on iOS 7, where full screen layout
+ // is the only way.
+ if (iosVersion < QSysInfo::MV_IOS_7_0)
+ self.window.rootViewController.wantsFullScreenLayout = YES;
+
+ // Use translucent statusbar by default on iOS6 iPhones (unless the user changed
+ // the default in the Info.plist), so that windows placed under the stausbar are
+ // still visible, just like on iOS7.
+ if (iosVersion >= QSysInfo::MV_IOS_6_0 && iosVersion < QSysInfo::MV_IOS_7_0
+ && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone
+ && [UIApplication sharedApplication].statusBarStyle == UIStatusBarStyleDefault)
+ [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
+#endif
+
self.window.hidden = NO;
return YES;
diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm
index 2dadc5672b..5ea5fbd8d1 100644
--- a/src/plugins/platforms/ios/qiosbackingstore.mm
+++ b/src/plugins/platforms/ios/qiosbackingstore.mm
@@ -56,6 +56,9 @@ QIOSBackingStore::QIOSBackingStore(QWindow *window)
fmt.setDepthBufferSize(16);
fmt.setStencilBufferSize(8);
+ // Needed to prevent QOpenGLContext::makeCurrent() from failing
+ window->setSurfaceType(QSurface::OpenGLSurface);
+
m_context->setFormat(fmt);
m_context->setScreen(window->screen());
m_context->create();
@@ -69,9 +72,6 @@ QIOSBackingStore::~QIOSBackingStore()
void QIOSBackingStore::beginPaint(const QRegion &)
{
- // Needed to prevent QOpenGLContext::makeCurrent() from failing
- window()->setSurfaceType(QSurface::OpenGLSurface);
-
m_context->makeCurrent(window());
QIOSWindow *iosWindow = static_cast<QIOSWindow *>(window()->handle());
@@ -102,6 +102,8 @@ void QIOSBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
// the child window overlaps a sibling window that's draws using a separate QOpenGLContext.
return;
}
+
+ m_context->makeCurrent(window);
m_context->swapBuffers(window);
}
@@ -115,7 +117,7 @@ void QIOSBackingStore::resize(const QSize &size, const QRegion &staticContents)
// backing store and always keep the paint device's size in sync with the
// window size in beginPaint().
- if (size != window()->size())
+ if (size != window()->size() && !window()->inherits("QWidgetWindow"))
qWarning() << "QIOSBackingStore needs to have the same size as its window";
}
diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h
index 41b0d7f93a..1c76d29389 100644
--- a/src/plugins/platforms/ios/qiosglobal.h
+++ b/src/plugins/platforms/ios/qiosglobal.h
@@ -53,10 +53,11 @@ class QPlatformScreen;
bool isQtApplication();
-CGRect toCGRect(const QRect &rect);
-QRect fromCGRect(const CGRect &rect);
-CGPoint toCGPoint(const QPoint &point);
-QPoint fromCGPoint(const CGPoint &point);
+CGRect toCGRect(const QRectF &rect);
+QRectF fromCGRect(const CGRect &rect);
+CGPoint toCGPoint(const QPointF &point);
+QPointF fromCGPoint(const CGPoint &point);
+
Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation);
UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation);
QRect fromPortraitToPrimary(const QRect &rect, QPlatformScreen *screen);
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
index be68e4d7d5..d749b8f514 100644
--- a/src/plugins/platforms/ios/qiosglobal.mm
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -58,24 +58,24 @@ bool isQtApplication()
return isQt;
}
-CGRect toCGRect(const QRect &rect)
+CGRect toCGRect(const QRectF &rect)
{
return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
}
-QRect fromCGRect(const CGRect &rect)
+QRectF fromCGRect(const CGRect &rect)
{
- return QRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+ return QRectF(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
}
-CGPoint toCGPoint(const QPoint &point)
+CGPoint toCGPoint(const QPointF &point)
{
return CGPointMake(point.x(), point.y());
}
-QPoint fromCGPoint(const CGPoint &point)
+QPointF fromCGPoint(const CGPoint &point)
{
- return QPoint(point.x, point.y);
+ return QPointF(point.x, point.y);
}
Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation)
diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h
index 78c1b260e6..533ba686e1 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.h
+++ b/src/plugins/platforms/ios/qiosinputcontext.h
@@ -44,6 +44,7 @@
#include <UIKit/UIKit.h>
+#include <QtGui/qtransform.h>
#include <qpa/qplatforminputcontext.h>
QT_BEGIN_NAMESPACE
@@ -60,13 +61,17 @@ public:
void showInputPanel();
void hideInputPanel();
bool isInputPanelVisible() const;
+ void setFocusObject(QObject *object);
- void focusViewChanged(UIView *view);
+ void focusWindowChanged(QWindow *focusWindow);
+ void scrollRootView();
private:
QIOSKeyboardListener *m_keyboardListener;
- UIView *m_focusView;
+ UIView<UIKeyInput> *m_focusView;
+ QTransform m_inputItemTransform;
bool m_hasPendingHideRequest;
+ bool m_inSetFocusObject;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index d430589037..0e43429015 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -48,7 +48,12 @@
@public
QIOSInputContext *m_context;
BOOL m_keyboardVisible;
+ BOOL m_keyboardVisibleAndDocked;
QRectF m_keyboardRect;
+ QRectF m_keyboardEndRect;
+ NSTimeInterval m_duration;
+ UIViewAnimationCurve m_curve;
+ UIViewController *m_viewController;
}
@end
@@ -60,8 +65,30 @@
if (self) {
m_context = context;
m_keyboardVisible = NO;
- // After the keyboard became undockable (iOS5), UIKeyboardWillShow/UIKeyboardWillHide
- // no longer works for all cases. So listen to keyboard frame changes instead:
+ m_keyboardVisibleAndDocked = NO;
+ m_duration = 0;
+ m_curve = UIViewAnimationCurveEaseOut;
+ m_viewController = 0;
+
+ if (isQtApplication()) {
+ // Get the root view controller that is on the same screen as the keyboard:
+ for (UIWindow *uiWindow in [[UIApplication sharedApplication] windows]) {
+ if (uiWindow.screen == [UIScreen mainScreen]) {
+ m_viewController = [uiWindow.rootViewController retain];
+ break;
+ }
+ }
+ Q_ASSERT(m_viewController);
+ }
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(keyboardWillShow:)
+ name:@"UIKeyboardWillShowNotification" object:nil];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(keyboardWillHide:)
+ name:@"UIKeyboardWillHideNotification" object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardDidChangeFrame:)
@@ -72,25 +99,68 @@
- (void) dealloc
{
+ [m_viewController release];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:@"UIKeyboardWillShowNotification" object:nil];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:@"UIKeyboardWillHideNotification" object:nil];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:@"UIKeyboardDidChangeFrameNotification" object:nil];
[super dealloc];
}
-- (void) keyboardDidChangeFrame:(NSNotification *)notification
+- (QRectF) getKeyboardRect:(NSNotification *)notification
{
- CGRect frame;
- [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&frame];
+ // For Qt applications we rotate the keyboard rect to align with the screen
+ // orientation (which is the interface orientation of the root view controller).
+ // For hybrid apps we follow native behavior, and return the rect unmodified:
+ CGRect keyboardFrame = [[notification userInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue];
+ if (isQtApplication()) {
+ UIView *view = m_viewController.view;
+ return fromCGRect(CGRectOffset([view convertRect:keyboardFrame fromView:view.window], 0, -view.bounds.origin.y));
+ } else {
+ return fromCGRect(keyboardFrame);
+ }
+}
- m_keyboardRect = fromPortraitToPrimary(fromCGRect(frame), QGuiApplication::primaryScreen()->handle());
+- (void) keyboardDidChangeFrame:(NSNotification *)notification
+{
+ m_keyboardRect = [self getKeyboardRect:notification];
m_context->emitKeyboardRectChanged();
- BOOL visible = CGRectIntersectsRect(frame, [UIScreen mainScreen].bounds);
+ BOOL visible = m_keyboardRect.intersects(fromCGRect([UIScreen mainScreen].bounds));
if (m_keyboardVisible != visible) {
m_keyboardVisible = visible;
m_context->emitInputPanelVisibleChanged();
}
+
+ // If the keyboard was visible and docked from before, this is just a geometry
+ // change (normally caused by an orientation change). In that case, update scroll:
+ if (m_keyboardVisibleAndDocked)
+ m_context->scrollRootView();
+}
+
+- (void) keyboardWillShow:(NSNotification *)notification
+{
+ // Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked.
+ m_keyboardVisibleAndDocked = YES;
+ m_keyboardEndRect = [self getKeyboardRect:notification];
+ if (!m_duration) {
+ m_duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
+ m_curve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16;
+ }
+ m_context->scrollRootView();
+}
+
+- (void) keyboardWillHide:(NSNotification *)notification
+{
+ // Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked.
+ m_keyboardVisibleAndDocked = NO;
+ m_keyboardEndRect = [self getKeyboardRect:notification];
+ m_context->scrollRootView();
}
@end
@@ -100,7 +170,11 @@ QIOSInputContext::QIOSInputContext()
, m_keyboardListener([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this])
, m_focusView(0)
, m_hasPendingHideRequest(false)
+ , m_inSetFocusObject(false)
{
+ if (isQtApplication())
+ connect(qGuiApp->inputMethod(), &QInputMethod::cursorRectangleChanged, this, &QIOSInputContext::scrollRootView);
+ connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &QIOSInputContext::focusWindowChanged);
}
QIOSInputContext::~QIOSInputContext()
@@ -142,10 +216,76 @@ bool QIOSInputContext::isInputPanelVisible() const
return m_keyboardListener->m_keyboardVisible;
}
-void QIOSInputContext::focusViewChanged(UIView *view)
+void QIOSInputContext::setFocusObject(QObject *)
+{
+ m_inputItemTransform = qApp->inputMethod()->inputItemTransform();
+
+ if (!m_focusView || !m_focusView.isFirstResponder)
+ return;
+
+ // Since m_focusView is the first responder, it means that the keyboard is open and we
+ // should update keyboard layout. But there seem to be no way to tell it to reread the
+ // UITextInputTraits from m_focusView. To work around that, we quickly resign first
+ // responder status just to reassign it again. To not remove the focusObject in the same
+ // go, we need to call the super implementation of resignFirstResponder. Since the call
+ // will cause a 'keyboardWillHide' notification to be sendt, we also block scrollRootView
+ // to avoid artifacts:
+ m_inSetFocusObject = true;
+ SEL sel = @selector(resignFirstResponder);
+ [[m_focusView superclass] instanceMethodForSelector:sel](m_focusView, sel);
+ m_inSetFocusObject = false;
+ [m_focusView becomeFirstResponder];
+}
+
+void QIOSInputContext::focusWindowChanged(QWindow *focusWindow)
{
+ UIView<UIKeyInput> *view = reinterpret_cast<UIView<UIKeyInput> *>(focusWindow->handle()->winId());
if ([m_focusView isFirstResponder])
[view becomeFirstResponder];
[m_focusView release];
m_focusView = [view retain];
}
+
+void QIOSInputContext::scrollRootView()
+{
+ // Scroll the root view (screen) if:
+ // - our backend controls the root view controller on the main screen (no hybrid app)
+ // - the focus object is on the same screen as the keyboard.
+ // - the first responder is a QUIView, and not some other foreign UIView.
+ // - the keyboard is docked. Otherwise the user can move the keyboard instead.
+ // - the inputItem has not been moved/scrolled
+ if (!isQtApplication() || !m_focusView || m_inSetFocusObject)
+ return;
+
+ if (m_inputItemTransform != qApp->inputMethod()->inputItemTransform()) {
+ // The inputItem has moved since the last scroll update. To avoid competing
+ // with the application where the cursor/inputItem should be, we bail:
+ return;
+ }
+
+ UIView *view = m_keyboardListener->m_viewController.view;
+ qreal scrollTo = 0;
+
+ if (m_focusView.isFirstResponder
+ && m_keyboardListener->m_keyboardVisibleAndDocked
+ && m_focusView.window == view.window) {
+ QRectF cursorRect = qGuiApp->inputMethod()->cursorRectangle();
+ cursorRect.translate(qGuiApp->focusWindow()->geometry().topLeft());
+ qreal keyboardY = m_keyboardListener->m_keyboardEndRect.y();
+ int statusBarY = qGuiApp->primaryScreen()->availableGeometry().y();
+ const int margin = 20;
+
+ if (cursorRect.bottomLeft().y() > keyboardY - margin)
+ scrollTo = qMin(view.bounds.size.height - keyboardY, cursorRect.y() - statusBarY - margin);
+ }
+
+ if (scrollTo != view.bounds.origin.y) {
+ // Scroll the view the same way a UIScrollView works: by changing bounds.origin:
+ CGRect newBounds = view.bounds;
+ newBounds.origin.y = scrollTo;
+ [UIView animateWithDuration:m_keyboardListener->m_duration delay:0
+ options:m_keyboardListener->m_curve
+ animations:^{ view.bounds = newBounds; }
+ completion:0];
+ }
+}
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 44ac749454..5c8f67bda2 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -160,7 +160,7 @@ QPlatformServices *QIOSIntegration::services() const
QVariant QIOSIntegration::styleHint(StyleHint hint) const
{
switch (hint) {
- case ShowIsFullScreen:
+ case ShowIsMaximized:
return true;
case SetFocusOnTouchRelease:
return true;
diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h
index e70ff4b1a9..173bd11719 100644
--- a/src/plugins/platforms/ios/qiosscreen.h
+++ b/src/plugins/platforms/ios/qiosscreen.h
@@ -50,8 +50,10 @@
QT_BEGIN_NAMESPACE
-class QIOSScreen : public QPlatformScreen
+class QIOSScreen : public QObject, public QPlatformScreen
{
+ Q_OBJECT
+
public:
QIOSScreen(unsigned int screenIndex);
~QIOSScreen();
@@ -73,6 +75,10 @@ public:
UIScreen *uiScreen() const;
void updateProperties();
+ void layoutWindows();
+
+public slots:
+ void updateStatusBarVisibility();
private:
UIScreen *m_uiScreen;
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index de6585fd19..57522cb1a3 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -139,6 +139,8 @@ QIOSScreen::QIOSScreen(unsigned int screenIndex)
m_unscaledDpi = 163; // Regular iPhone DPI
}
+ connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &QIOSScreen::updateStatusBarVisibility);
+
updateProperties();
}
@@ -156,7 +158,7 @@ void QIOSScreen::updateProperties()
}
bool inPortrait = UIInterfaceOrientationIsPortrait(uiWindow.rootViewController.interfaceOrientation);
- QRect geometry = inPortrait ? fromCGRect(m_uiScreen.bounds)
+ QRect geometry = inPortrait ? fromCGRect(m_uiScreen.bounds).toRect()
: QRect(m_uiScreen.bounds.origin.x, m_uiScreen.bounds.origin.y,
m_uiScreen.bounds.size.height, m_uiScreen.bounds.size.width);
@@ -182,7 +184,66 @@ void QIOSScreen::updateProperties()
}
if (screen())
- resizeMaximizedWindows();
+ layoutWindows();
+}
+
+void QIOSScreen::updateStatusBarVisibility()
+{
+ QWindow *focusWindow = QGuiApplication::focusWindow();
+
+ // If we don't have a focus window we leave the status
+ // bar as is, so that the user can activate a new window
+ // with the same window state without the status bar jumping
+ // back and forth.
+ if (!focusWindow)
+ return;
+
+ UIView *view = reinterpret_cast<UIView *>(focusWindow->handle()->winId());
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) {
+ [view.viewController setNeedsStatusBarAppearanceUpdate];
+ } else
+#endif
+ {
+ bool wasHidden = [UIApplication sharedApplication].statusBarHidden;
+ QIOSViewController *viewController = static_cast<QIOSViewController *>(view.viewController);
+ [[UIApplication sharedApplication]
+ setStatusBarHidden:[viewController prefersStatusBarHidden]
+ withAnimation:UIStatusBarAnimationNone];
+
+ if ([UIApplication sharedApplication].statusBarHidden != wasHidden)
+ updateProperties();
+ }
+}
+
+void QIOSScreen::layoutWindows()
+{
+ QList<QWindow*> windows = QGuiApplication::topLevelWindows();
+
+ const QRect oldGeometry = screen()->geometry();
+ const QRect oldAvailableGeometry = screen()->availableGeometry();
+ const QRect newGeometry = geometry();
+ const QRect newAvailableGeometry = availableGeometry();
+
+ for (int i = 0; i < windows.size(); ++i) {
+ QWindow *window = windows.at(i);
+
+ if (platformScreenForWindow(window) != this)
+ continue;
+
+ QIOSWindow *platformWindow = static_cast<QIOSWindow *>(window->handle());
+ if (!platformWindow)
+ continue;
+
+ // FIXME: Handle more complex cases of no-state and/or child windows when rotating
+
+ if (window->windowState() & Qt::WindowFullScreen
+ || (window->windowState() & Qt::WindowNoState && window->geometry() == oldGeometry))
+ platformWindow->applyGeometry(newGeometry);
+ else if (window->windowState() & Qt::WindowMaximized
+ || (window->windowState() & Qt::WindowNoState && window->geometry() == oldAvailableGeometry))
+ platformWindow->applyGeometry(newAvailableGeometry);
+ }
}
QRect QIOSScreen::geometry() const
@@ -247,4 +308,6 @@ UIScreen *QIOSScreen::uiScreen() const
return m_uiScreen;
}
+#include "moc_qiosscreen.cpp"
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index d5a61cb3f4..a0017808d3 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -42,5 +42,6 @@
#import <UIKit/UIKit.h>
@interface QIOSViewController : UIViewController
+- (BOOL)prefersStatusBarHidden;
@end
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 1d5e69beac..2e7e44d32c 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -42,9 +42,11 @@
#import "qiosviewcontroller.h"
#include <QtGui/QGuiApplication>
+#include <QtGui/QWindow>
#include <QtGui/QScreen>
#include "qiosscreen.h"
#include "qiosglobal.h"
+#include "qioswindow.h"
@implementation QIOSViewController
@@ -55,12 +57,22 @@
return YES;
}
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_6_0)
-(NSUInteger)supportedInterfaceOrientations
{
// We need to tell iOS that we support all orientations in order to set
// status bar orientation when application content orientation changes.
return UIInterfaceOrientationMaskAll;
}
+#endif
+
+#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
+-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ Q_UNUSED(interfaceOrientation);
+ return YES;
+}
+#endif
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
@@ -74,5 +86,28 @@
qiosScreen->updateProperties();
}
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
+- (UIStatusBarStyle)preferredStatusBarStyle
+{
+ // Since we don't place anything behind the status bare by default, we
+ // end up with a black area, so we have to enable the white text mode
+ // of the iOS7 statusbar.
+ return UIStatusBarStyleLightContent;
+
+ // FIXME: Try to detect the content underneath the statusbar and choose
+ // an appropriate style, and/or expose Qt APIs to control the style.
+}
+#endif
+
+- (BOOL)prefersStatusBarHidden
+{
+ QWindow *focusWindow = QGuiApplication::focusWindow();
+ if (!focusWindow)
+ return [UIApplication sharedApplication].statusBarHidden;
+
+ QIOSWindow *topLevel = static_cast<QIOSWindow *>(focusWindow->handle())->topLevelWindow();
+ return topLevel->window()->windowState() == Qt::WindowFullScreen;
+}
+
@end
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index 6e8683af00..a5e122bda1 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -85,7 +85,11 @@ public:
WId winId() const { return WId(m_view); };
+ QIOSWindow *topLevelWindow() const;
+
private:
+ void applyGeometry(const QRect &rect);
+
QUIView *m_view;
QRect m_normalGeometry;
@@ -97,6 +101,8 @@ private:
inline Qt::WindowType windowType() { return static_cast<Qt::WindowType>(int(window()->flags() & Qt::WindowType_Mask)); }
inline bool windowIsPopup() { return windowType() & Qt::Popup & ~Qt::Window; }
+
+ friend class QIOSScreen;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 2413a45e11..0dd810bdf6 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -105,18 +105,10 @@
CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
+ [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
- // Set up text input
- autocapitalizationType = UITextAutocapitalizationTypeNone;
- autocorrectionType = UITextAutocorrectionTypeNo;
- enablesReturnKeyAutomatically = NO;
- keyboardAppearance = UIKeyboardAppearanceDefault;
- keyboardType = UIKeyboardTypeDefault;
- returnKeyType = UIReturnKeyDone;
- secureTextEntry = NO;
- m_nextTouchId = 0;
+ [self updateTextInputTraits];
if (isQtApplication())
self.hidden = YES;
@@ -153,6 +145,15 @@
self.clipsToBounds = NO;
}
+- (void)setNeedsDisplay
+{
+ [super setNeedsDisplay];
+
+ // We didn't implement drawRect: so we have to manually
+ // mark the layer as needing display.
+ [self.layer setNeedsDisplay];
+}
+
- (void)layoutSubviews
{
// This method is the de facto way to know that view has been resized,
@@ -165,15 +166,53 @@
qWarning() << m_qioswindow->window()
<< "is backed by a UIView that has a transform set. This is not supported.";
- QRect geometry = fromCGRect(self.frame);
- m_qioswindow->QPlatformWindow::setGeometry(geometry);
- QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), geometry);
- QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), QRect(QPoint(), geometry.size()));
+ // The original geometry requested by setGeometry() might be different
+ // from what we end up with after applying window constraints.
+ QRect requestedGeometry = m_qioswindow->geometry();
+
+ QRect actualGeometry;
+ if (m_qioswindow->window()->isTopLevel()) {
+ UIWindow *uiWindow = self.window;
+ UIView *rootView = uiWindow.rootViewController.view;
+ CGRect rootViewPositionInRelationToRootViewController =
+ [rootView convertRect:uiWindow.bounds fromView:uiWindow];
+
+ actualGeometry = fromCGRect(CGRectOffset([self.superview convertRect:self.frame toView:rootView],
+ -rootViewPositionInRelationToRootViewController.origin.x,
+ -rootViewPositionInRelationToRootViewController.origin.y
+ + rootView.bounds.origin.y)).toRect();
+ } else {
+ actualGeometry = fromCGRect(self.frame).toRect();
+ }
+
+ // Persist the actual/new geometry so that QWindow::geometry() can
+ // be queried on the resize event.
+ m_qioswindow->QPlatformWindow::setGeometry(actualGeometry);
+
+ QRect previousGeometry = requestedGeometry != actualGeometry ?
+ requestedGeometry : qt_window_private(m_qioswindow->window())->geometry;
+
+ QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), actualGeometry, previousGeometry);
+ QWindowSystemInterface::flushWindowSystemEvents();
- // If we have a new size here we need to resize the FBO's corresponding buffers,
- // but we defer that to when the application calls makeCurrent.
+ if (actualGeometry.size() != previousGeometry.size()) {
+ // Trigger expose event on resize
+ [self setNeedsDisplay];
- [super layoutSubviews];
+ // A new size means we also need to resize the FBO's corresponding buffers,
+ // but we defer that to when the application calls makeCurrent.
+ }
+}
+
+- (void)displayLayer:(CALayer *)layer
+{
+ QRect geometry = fromCGRect(layer.frame).toRect();
+ Q_ASSERT(m_qioswindow->geometry() == geometry);
+ Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
+
+ QRegion region = self.hidden ? QRegion() : QRect(QPoint(), geometry.size());
+ QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
+ QWindowSystemInterface::flushWindowSystemEvents();
}
- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
@@ -195,7 +234,7 @@
} else {
touchPoint.state = state;
touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
- QPoint touchPos = fromCGPoint([uiTouch locationInView:rootView]);
+ QPoint touchPos = fromCGPoint([uiTouch locationInView:rootView]).toPoint();
touchPoint.area = QRectF(touchPos, QSize(0, 0));
touchPoint.normalPosition = QPointF(touchPos.x() / rootViewSize.width, touchPos.y() / rootViewSize.height);
}
@@ -296,6 +335,7 @@
// user cannot type. And since the keyboard will open when a view becomes
// the first responder, it's now a good time to inform QPA that the QWindow
// this view backs became active:
+ [self updateTextInputTraits];
QWindowSystemInterface::handleWindowActivated(m_qioswindow->window());
return [super becomeFirstResponder];
}
@@ -318,8 +358,11 @@
{
QString string = QString::fromUtf8([text UTF8String]);
int key = 0;
- if ([text isEqualToString:@"\n"])
+ if ([text isEqualToString:@"\n"]) {
key = (int)Qt::Key_Return;
+ if (self.returnKeyType == UIReturnKeyDone)
+ [self resignFirstResponder];
+ }
// Send key event to window system interface
QWindowSystemInterface::handleKeyEvent(
@@ -337,6 +380,47 @@
0, QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier);
}
+- (void)updateTextInputTraits
+{
+ // Ask the current focus object what kind of input it
+ // expects, and configure the keyboard appropriately:
+ QObject *focusObject = QGuiApplication::focusObject();
+ if (!focusObject)
+ return;
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints);
+ if (!QCoreApplication::sendEvent(focusObject, &queryEvent))
+ return;
+ if (!queryEvent.value(Qt::ImEnabled).toBool())
+ return;
+
+ Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt());
+
+ self.returnKeyType = (hints & Qt::ImhMultiLine) ? UIReturnKeyDefault : UIReturnKeyDone;
+ self.secureTextEntry = BOOL(hints & Qt::ImhHiddenText);
+ self.autocorrectionType = (hints & Qt::ImhNoPredictiveText) ?
+ UITextAutocorrectionTypeNo : UITextAutocorrectionTypeDefault;
+
+ if (hints & Qt::ImhUppercaseOnly)
+ self.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
+ else if (hints & Qt::ImhNoAutoUppercase)
+ self.autocapitalizationType = UITextAutocapitalizationTypeNone;
+ else
+ self.autocapitalizationType = UITextAutocapitalizationTypeSentences;
+
+ if (hints & Qt::ImhUrlCharactersOnly)
+ self.keyboardType = UIKeyboardTypeURL;
+ else if (hints & Qt::ImhEmailCharactersOnly)
+ self.keyboardType = UIKeyboardTypeEmailAddress;
+ else if (hints & Qt::ImhDigitsOnly)
+ self.keyboardType = UIKeyboardTypeNumberPad;
+ else if (hints & Qt::ImhFormattedNumbersOnly)
+ self.keyboardType = UIKeyboardTypeDecimalPad;
+ else if (hints & Qt::ImhDialableCharactersOnly)
+ self.keyboardType = UIKeyboardTypeNumberPad;
+ else
+ self.keyboardType = UIKeyboardTypeDefault;
+}
+
@end
@implementation UIView (QIOS)
@@ -393,8 +477,8 @@ bool QIOSWindow::blockedByModal()
void QIOSWindow::setVisible(bool visible)
{
- QPlatformWindow::setVisible(visible);
m_view.hidden = !visible;
+ [m_view setNeedsDisplay];
if (!isQtApplication())
return;
@@ -412,6 +496,10 @@ void QIOSWindow::setVisible(bool visible)
if (visible) {
requestActivateWindow();
+
+ if (window()->isTopLevel())
+ static_cast<QIOSScreen *>(screen())->updateStatusBarVisibility();
+
} else {
// Activate top-most visible QWindow:
NSArray *subviews = m_view.viewController.view.subviews;
@@ -429,40 +517,90 @@ void QIOSWindow::setVisible(bool visible)
void QIOSWindow::setGeometry(const QRect &rect)
{
- // If the window is in fullscreen, just bookkeep the requested
- // geometry in case the window goes into Qt::WindowNoState later:
m_normalGeometry = rect;
- if (window()->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen))
+
+ if (window()->windowState() != Qt::WindowNoState) {
+ QPlatformWindow::setGeometry(rect);
+
+ // The layout will realize the requested geometry was not applied, and
+ // send geometry-change events that match the actual geometry.
+ [m_view setNeedsLayout];
+
+ if (window()->inherits("QWidgetWindow")) {
+ // QWidget wrongly assumes that setGeometry resets the window
+ // state back to Qt::NoWindowState, so we need to inform it that
+ // that his is not the case by re-issuing the current window state.
+ QWindowSystemInterface::handleWindowStateChanged(window(), window()->windowState());
+
+ // It also needs to be told immediately that the geometry it requested
+ // did not apply, otherwise it will continue on as if it did, instead
+ // of waiting for a resize event.
+ [m_view layoutIfNeeded];
+ }
+
return;
+ }
- // Since we don't support transformations on the UIView, we can set the frame
- // directly and let UIKit deal with translating that into bounds and center.
- // Changing the size of the view will end up in a call to -[QUIView layoutSubviews]
- // which will update QWindowSystemInterface with the new size.
- m_view.frame = toCGRect(rect);
+ applyGeometry(rect);
+}
+
+void QIOSWindow::applyGeometry(const QRect &rect)
+{
+ // Geometry changes are asynchronous, but QWindow::geometry() is
+ // expected to report back the 'requested geometry' until we get
+ // a callback with the updated geometry from the window system.
+ // The baseclass takes care of persisting this for us.
+ QPlatformWindow::setGeometry(rect);
+
+ if (window()->isTopLevel()) {
+ // The QWindow is in QScreen coordinates, which maps to a possibly rotated root-view-controller.
+ // Since the root-view-controller might be translated in relation to the UIWindow, we need to
+ // check specifically for that and compensate. Also check if the root view has been scrolled
+ // as a result of the keyboard being open.
+ UIWindow *uiWindow = m_view.window;
+ UIView *rootView = uiWindow.rootViewController.view;
+ CGRect rootViewPositionInRelationToRootViewController =
+ [rootView convertRect:uiWindow.bounds fromView:uiWindow];
+
+ m_view.frame = CGRectOffset([m_view.superview convertRect:toCGRect(rect) fromView:rootView],
+ rootViewPositionInRelationToRootViewController.origin.x,
+ rootViewPositionInRelationToRootViewController.origin.y
+ + rootView.bounds.origin.y);
+ } else {
+ // Easy, in parent's coordinates
+ m_view.frame = toCGRect(rect);
+ }
+
+ // iOS will automatically trigger -[layoutSubviews:] for resize,
+ // but not for move, so we force it just in case.
+ [m_view setNeedsLayout];
+
+ if (window()->inherits("QWidgetWindow"))
+ [m_view layoutIfNeeded];
}
void QIOSWindow::setWindowState(Qt::WindowState state)
{
- // FIXME: Figure out where or how we should disable/enable the statusbar.
- // Perhaps setting QWindow to maximized should also mean that we'll show
- // the statusbar, and vice versa for fullscreen?
+ // Update the QWindow representation straight away, so that
+ // we can update the statusbar visibility based on the new
+ // state before applying geometry changes.
+ qt_window_private(window())->windowState = state;
- if (state != Qt::WindowNoState)
- m_normalGeometry = geometry();
+ if (window()->isTopLevel() && window()->isVisible() && window()->isActive())
+ static_cast<QIOSScreen *>(screen())->updateStatusBarVisibility();
switch (state) {
case Qt::WindowNoState:
- setGeometry(m_normalGeometry);
+ applyGeometry(m_normalGeometry);
break;
case Qt::WindowMaximized:
- setGeometry(screen()->availableGeometry());
+ applyGeometry(screen()->availableGeometry());
break;
case Qt::WindowFullScreen:
- setGeometry(screen()->geometry());
+ applyGeometry(screen()->geometry());
break;
case Qt::WindowMinimized:
- setGeometry(QRect());
+ applyGeometry(QRect());
break;
case Qt::WindowActive:
Q_UNREACHABLE();
@@ -486,6 +624,23 @@ void QIOSWindow::setParent(const QPlatformWindow *parentWindow)
}
}
+QIOSWindow *QIOSWindow::topLevelWindow() const
+{
+ QWindow *window = this->window();
+ while (window) {
+ QWindow *parent = window->parent();
+ if (!parent)
+ parent = window->transientParent();
+
+ if (!parent)
+ break;
+
+ window = parent;
+ }
+
+ return static_cast<QIOSWindow *>(window->handle());
+}
+
void QIOSWindow::requestActivateWindow()
{
// Note that several windows can be active at the same time if they exist in the same
@@ -499,8 +654,6 @@ void QIOSWindow::requestActivateWindow()
if (window()->isTopLevel())
raise();
- QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
- static_cast<QIOSInputContext *>(context)->focusViewChanged(m_view);
QWindowSystemInterface::handleWindowActivated(window());
}
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index aeacbeef69..bc7219de5c 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -2,9 +2,6 @@ TARGET = qqnx
QT += platformsupport-private core-private gui-private
-# The PPS based platform integration is currently used for both BB10 and plain QNX
-CONFIG += qqnx_pps
-
# Uncomment this to build with support for IMF once it becomes available in the BBNDK
#CONFIG += qqnx_imf
@@ -132,7 +129,8 @@ CONFIG(qqnx_pps) {
qqnxclipboard.h \
qqnxbuttoneventnotifier.h
- LIBS += -lpps -lclipboard
+ LIBS += -lpps
+ !contains(DEFINES, QT_NO_CLIPBOARD): LIBS += -lclipboard
CONFIG(qqnx_imf) {
DEFINES += QQNX_IMF
diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp
index 6afc3cad21..b57227a60b 100644
--- a/src/plugins/platforms/qnx/qqnxeglwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxeglwindow.cpp
@@ -58,12 +58,13 @@ QT_BEGIN_NAMESPACE
QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool needRootWindow) :
QQnxWindow(window, context, needRootWindow),
- m_requestedBufferSize(window->geometry().size()),
m_platformOpenGLContext(0),
m_newSurfaceRequested(true),
m_eglSurface(EGL_NO_SURFACE)
{
initWindow();
+ m_requestedBufferSize = screen()->rootWindow() == this ?
+ screen()->geometry().size() : window->geometry().size();
}
QQnxEglWindow::~QQnxEglWindow()
@@ -145,6 +146,9 @@ EGLSurface QQnxEglWindow::getSurface()
void QQnxEglWindow::setGeometry(const QRect &rect)
{
+ //If this is the root window, it has to be shown fullscreen
+ const QRect &newGeometry = screen()->rootWindow() == this ? screen()->geometry() : rect;
+
//We need to request that the GL context updates
// the EGLsurface on which it is rendering.
{
@@ -152,11 +156,11 @@ void QQnxEglWindow::setGeometry(const QRect &rect)
// setting m_requestedBufferSize and therefore extended the scope to include
// that test.
const QMutexLocker locker(&m_mutex);
- m_requestedBufferSize = rect.size();
- if (m_platformOpenGLContext != 0 && bufferSize() != rect.size())
+ m_requestedBufferSize = newGeometry.size();
+ if (m_platformOpenGLContext != 0 && bufferSize() != newGeometry.size())
m_newSurfaceRequested.testAndSetRelease(false, true);
}
- QQnxWindow::setGeometry(rect);
+ QQnxWindow::setGeometry(newGeometry);
}
QSize QQnxEglWindow::requestedBufferSize() const
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 1e58d482d4..b25c0b5b29 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -136,7 +136,7 @@ void QQnxWindow::setGeometry(const QRect &rect)
// Calling flushWindowSystemEvents() here would flush input events which
// could result in re-entering QQnxWindow::setGeometry() again.
- QWindowSystemInterface::setSynchronousWindowsSystemEvents(true); //This does not work
+ QWindowSystemInterface::setSynchronousWindowsSystemEvents(true);
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
QWindowSystemInterface::setSynchronousWindowsSystemEvents(false);
@@ -608,13 +608,15 @@ void QQnxWindow::initWindow()
setWindowState(window()->windowState());
if (window()->parent() && window()->parent()->handle())
setParent(window()->parent()->handle());
- setGeometryHelper(window()->geometry());
+
if (screen()->rootWindow() == this) {
- setGeometry(screen()->geometry());
+ setGeometryHelper(screen()->geometry());
+ QWindowSystemInterface::handleGeometryChange(window(), screen()->geometry());
+ } else {
+ setGeometryHelper(window()->geometry());
}
}
-
void QQnxWindow::createWindowGroup()
{
// Generate a random window group name
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index e2594207fe..2743ef029d 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -86,6 +86,10 @@ QWindowsKeyMapper::~QWindowsKeyMapper()
#define VK_OEM_3 0xC0
#endif
+// We not only need the scancode itself but also the extended bit of key messages. Thus we need
+// the additional bit when masking the scancode.
+enum { scancodeBitmask = 0x1ff };
+
// Key recorder ------------------------------------------------------------------------[ start ] --
struct KeyRecord {
KeyRecord(int c, int a, int s, const QString &t) : code(c), ascii(a), state(s), text(t) {}
@@ -567,7 +571,7 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg)
{
unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
GetKeyboardState(kbdBuffer);
- const quint32 scancode = (msg.lParam >> 16) & 0xff;
+ const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
updatePossibleKeyCodes(kbdBuffer, scancode, msg.wParam);
}
@@ -754,7 +758,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
{
const int msgType = msg.message;
- const quint32 scancode = (msg.lParam >> 16) & 0xff;
+ const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
const quint32 vk_key = msg.wParam;
quint32 nModifiers = 0;
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index e6fa8fc898..e504d93fba 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -415,12 +415,17 @@ bool QGLXContext::m_supportsThreading = true;
// If this list grows to any significant size, change it a
// proper string table and make the implementation below use
// binary search.
-static const char *qglx_threadedgl_blacklist[] = {
+static const char *qglx_threadedgl_blacklist_renderer[] = {
"Chromium", // QTBUG-32225 (initialization fails)
"Mesa DRI Intel(R) Sandybridge Mobile", // QTBUG-34492 (flickering in fullscreen)
0
};
+static const char *qglx_threadedgl_blacklist_vendor[] = {
+ "nouveau", // QTCREATORBUG-10875 (crash in creator)
+ 0
+};
+
void QGLXContext::queryDummyContext()
{
if (m_queriedDummyContext)
@@ -437,8 +442,8 @@ void QGLXContext::queryDummyContext()
oldSurface = oldContext->surface();
QScopedPointer<QSurface> surface;
- const char *vendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR);
- if (vendor && !strcmp(vendor, "ATI")) {
+ const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR);
+ if (glxvendor && !strcmp(glxvendor, "ATI")) {
QWindow *window = new QWindow;
window->resize(64, 64);
window->setSurfaceType(QSurface::OpenGLSurface);
@@ -454,11 +459,19 @@ void QGLXContext::queryDummyContext()
context.create();
context.makeCurrent(surface.data());
+ m_supportsThreading = true;
+
const char *renderer = (const char *) glGetString(GL_RENDERER);
+ for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) {
+ if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) {
+ m_supportsThreading = false;
+ break;
+ }
+ }
- m_supportsThreading = true;
- for (int i = 0; qglx_threadedgl_blacklist[i]; ++i) {
- if (strstr(renderer, qglx_threadedgl_blacklist[i]) != 0) {
+ const char *vendor = (const char *) glGetString(GL_VENDOR);
+ for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) {
+ if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) {
m_supportsThreading = false;
break;
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index cc8c42f96b..4d2735ca85 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -1749,10 +1749,26 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, doub
return true;
}
-bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode)
+// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
+// - "pad0" became "extension"
+// - "pad1" and "pad" became "pad0"
+// New and old version of this struct share the following fields:
+// NOTE: API might change again in the next release of xcb in which case this comment will
+// need to be updated to reflect the reality.
+typedef struct qt_xcb_ge_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+} qt_xcb_ge_event_t;
+
+bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCode)
{
- // xGenericEvent has "extension" on the second byte, xcb_ge_event_t has "pad0".
- if (event->pad0 == opCode) {
+ qt_xcb_ge_event_t *event = (qt_xcb_ge_event_t *)ev;
+ // xGenericEvent has "extension" on the second byte, the same is true for xcb_ge_event_t starting from
+ // the xcb version 1.9.3, prior to that it was called "pad0".
+ if (event->extension == opCode) {
// xcb event structs contain stuff that wasn't on the wire, the full_sequence field
// adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
// Move this data back to have the same layout in memory as it was on the wire