summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-02-21 01:00:08 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-02-21 01:00:08 +0100
commit0c0c4a23bc55619c59d2cd0ccd4d4b19bb1fea59 (patch)
tree0e56c0e3a3acb05232949b6a5d3e18feb48eb25e /src/plugins/platforms
parenta4b8e7141b3dd3bf3c2ac139b44ece0f74b054d8 (diff)
parent904617dfb83f39a6a379635b64fea6fcd00f241a (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/android/qandroidsystemlocale.cpp18
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm48
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.h11
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm219
8 files changed, 138 insertions, 173 deletions
diff --git a/src/plugins/platforms/android/qandroidsystemlocale.cpp b/src/plugins/platforms/android/qandroidsystemlocale.cpp
index 7fe36aa9bc..f9d566ff1a 100644
--- a/src/plugins/platforms/android/qandroidsystemlocale.cpp
+++ b/src/plugins/platforms/android/qandroidsystemlocale.cpp
@@ -40,6 +40,7 @@
#include "qandroidsystemlocale.h"
#include "androidjnimain.h"
#include <QtCore/private/qjni_p.h>
+#include <QtCore/private/qjnihelpers_p.h>
#include "qdatetime.h"
#include "qstringlist.h"
#include "qvariant.h"
@@ -162,6 +163,23 @@ QVariant QAndroidSystemLocale::query(QueryType type, QVariant in) const
return m_locale.createSeparatedList(in.value<QStringList>());
case LocaleChanged:
Q_ASSERT_X(false, Q_FUNC_INFO, "This can't happen.");
+ case UILanguages: {
+ if (QtAndroidPrivate::androidSdkVersion() >= 24) {
+ QJNIObjectPrivate localeListObject =
+ QJNIObjectPrivate::callStaticObjectMethod("android/os/LocaleList", "getDefault",
+ "()Landroid/os/LocaleList;");
+ if (localeListObject.isValid()) {
+ QString lang = localeListObject.callObjectMethod("toLanguageTags",
+ "()Ljava/lang/String;").toString();
+ // Some devices return with it enclosed in []'s so check if both exists before
+ // removing to ensure it is formatted correctly
+ if (lang.startsWith(QChar('[')) && lang.endsWith(QChar(']')))
+ lang = lang.mid(1, lang.length() - 2);
+ return lang.split(QChar(','));
+ }
+ }
+ return QVariant();
+ }
default:
break;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 9e3c89b6a4..2cf6672da9 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -94,7 +94,6 @@ QT_USE_NAMESPACE
bool startedQuit;
NSObject <NSApplicationDelegate> *reflectionDelegate;
bool inLaunch;
- QWindowList hiddenWindows;
}
+ (instancetype)sharedDelegate
@@ -116,22 +115,10 @@ QT_USE_NAMESPACE
self = [super init];
if (self) {
inLaunch = true;
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(updateScreens:)
- name:NSApplicationDidChangeScreenParametersNotification
- object:NSApp];
}
return self;
}
-- (void)updateScreens:(NSNotification *)notification
-{
- Q_UNUSED(notification);
- if (QCocoaIntegration *ci = QCocoaIntegration::instance())
- ci->updateScreens();
-}
-
- (void)dealloc
{
[_dockMenu release];
@@ -311,41 +298,6 @@ QT_USE_NAMESPACE
return NO; // Someday qApp->quitOnLastWindowClosed(); when QApp and NSApp work closer together.
}
-- (void)applicationWillHide:(NSNotification *)notification
-{
- if (reflectionDelegate
- && [reflectionDelegate respondsToSelector:@selector(applicationWillHide:)]) {
- [reflectionDelegate applicationWillHide:notification];
- }
-
- // When the application is hidden Qt will hide the popup windows associated with
- // it when it has lost the activation for the application. However, when it gets
- // to this point it believes the popup windows to be hidden already due to the
- // fact that the application itself is hidden, which will cause a problem when
- // the application is made visible again.
- const QWindowList topLevelWindows = QGuiApplication::topLevelWindows();
- for (QWindow *topLevelWindow : topLevelWindows) {
- if ((topLevelWindow->type() & Qt::Popup) == Qt::Popup && topLevelWindow->isVisible()) {
- topLevelWindow->hide();
-
- if ((topLevelWindow->type() & Qt::Tool) == Qt::Tool)
- hiddenWindows << topLevelWindow;
- }
- }
-}
-
-- (void)applicationDidUnhide:(NSNotification *)notification
-{
- if (reflectionDelegate
- && [reflectionDelegate respondsToSelector:@selector(applicationDidUnhide:)])
- [reflectionDelegate applicationDidUnhide:notification];
-
- for (QWindow *window : qAsConst(hiddenWindows))
- window->show();
-
- hiddenWindows.clear();
-}
-
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
if (reflectionDelegate
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 7de7e073de..04cb4e1226 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -144,6 +144,7 @@ private:
#endif
QScopedPointer<QPlatformTheme> mPlatformTheme;
QList<QCocoaScreen *> mScreens;
+ QMacScopedObserver m_screensObserver;
#ifndef QT_NO_CLIPBOARD
QCocoaClipboard *mCocoaClipboard;
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index f6a49dd74f..affbee35b7 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -206,6 +206,9 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
// by explicitly setting the presentation option to the magic 'default value',
// which will resolve to an actual value and result in screen invalidation.
cocoaApplication.presentationOptions = NSApplicationPresentationDefault;
+
+ m_screensObserver = QMacScopedObserver([NSApplication sharedApplication],
+ NSApplicationDidChangeScreenParametersNotification, [&]() { updateScreens(); });
updateScreens();
QMacInternalPasteboardMime::initializeMimeTypes();
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index 830a387fd1..6a5b0e6e3e 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -410,8 +410,7 @@ QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
if (![nsWindow conformsToProtocol:@protocol(QNSWindowProtocol)])
continue;
- id<QNSWindowProtocol> proto = static_cast<id<QNSWindowProtocol> >(nsWindow);
- QCocoaWindow *cocoaWindow = proto.platformWindow;
+ QCocoaWindow *cocoaWindow = qnsview_cast(nsWindow.contentView).platformWindow;
if (!cocoaWindow)
continue;
window = cocoaWindow->window();
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index fc772181f0..ff2c4de985 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -401,6 +401,11 @@ void QCocoaWindow::setVisible(bool visible)
}
}
+ // Note: We do not guard the order out by checking NSWindow.visible, as AppKit will
+ // in some cases, such as when hiding the application, order out and make a window
+ // invisible, but keep it in a list of "hidden windows", that it then restores again
+ // when the application is unhidden. We need to call orderOut explicitly, to bring
+ // the window out of this "hidden list".
[m_view.window orderOut:nil];
if (m_view.window == [NSApp keyWindow] && !eventDispatcher()->hasModalSession()) {
@@ -1540,7 +1545,8 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
// Deferring window creation breaks OpenGL (the GL context is
// set up before the window is shown and needs a proper window)
backing:NSBackingStoreBuffered defer:NO
- screen:cocoaScreen->nativeScreen()];
+ screen:cocoaScreen->nativeScreen()
+ platformWindow:this];
Q_ASSERT_X(nsWindow.screen == cocoaScreen->nativeScreen(), "QCocoaWindow",
"Resulting NSScreen should match the requested NSScreen");
diff --git a/src/plugins/platforms/cocoa/qnswindow.h b/src/plugins/platforms/cocoa/qnswindow.h
index dcbcd58901..5fc48d826f 100644
--- a/src/plugins/platforms/cocoa/qnswindow.h
+++ b/src/plugins/platforms/cocoa/qnswindow.h
@@ -60,15 +60,10 @@ QT_FORWARD_DECLARE_CLASS(QCocoaWindow)
#define QNSWindowProtocol QT_MANGLE_NAMESPACE(QNSWindowProtocol)
@protocol QNSWindowProtocol
-@optional
-- (BOOL)canBecomeKeyWindow;
-- (BOOL)worksWhenModal;
-- (void)sendEvent:(NSEvent*)theEvent;
+- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style
+ backing:(NSBackingStoreType)backingStoreType defer:(BOOL)flag screen:(NSScreen *)screen
+ platformWindow:(QCocoaWindow*)window;
- (void)closeAndRelease;
-- (void)dealloc;
-- (BOOL)isOpaque;
-- (NSColor *)backgroundColor;
-- (NSString *)description;
@property (nonatomic, readonly) QCocoaWindow *platformWindow;
@end
diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm
index 28a9fa8607..52f765eb31 100644
--- a/src/plugins/platforms/cocoa/qnswindow.mm
+++ b/src/plugins/platforms/cocoa/qnswindow.mm
@@ -37,6 +37,8 @@
**
****************************************************************************/
+#if !defined(QNSWINDOW_PROTOCOL_IMPLMENTATION)
+
#include "qnswindow.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
@@ -89,44 +91,104 @@ static bool isMouseEvent(NSEvent *ev)
}
@end
-#define super USE_qt_objcDynamicSuper_INSTEAD
-
@implementation QNSWindow
+#define QNSWINDOW_PROTOCOL_IMPLMENTATION 1
+#include "qnswindow.mm"
+#undef QNSWINDOW_PROTOCOL_IMPLMENTATION
-+ (void)load
++ (void)applicationActivationChanged:(NSNotification*)notification
{
- const Class windowClass = [self class];
- const Class panelClass = [QNSPanel class];
-
- unsigned int protocolCount;
- Protocol **protocols = class_copyProtocolList(windowClass, &protocolCount);
- for (unsigned int i = 0; i < protocolCount; ++i) {
- Protocol *protocol = protocols[i];
-
- unsigned int methodDescriptionsCount;
- objc_method_description *methods = protocol_copyMethodDescriptionList(
- protocol, NO, YES, &methodDescriptionsCount);
-
- for (unsigned int j = 0; j < methodDescriptionsCount; ++j) {
- objc_method_description method = methods[j];
- class_addMethod(panelClass, method.name,
- class_getMethodImplementation(windowClass, method.name),
- method.types);
+ const id sender = self;
+ NSEnumerator<NSWindow*> *windowEnumerator = nullptr;
+ NSApplication *application = [NSApplication sharedApplication];
+
+ // Unfortunately there's no NSWindowListOrderedBackToFront,
+ // so we have to manually reverse the order using an array.
+ NSMutableArray<NSWindow *> *windows = [NSMutableArray<NSWindow *> new];
+ [application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
+ usingBlock:^(NSWindow *window, BOOL *) {
+ // For some reason AppKit will give us nil-windows, skip those
+ if (!window)
+ return;
+
+ [windows addObject:window];
+ }
+ ];
+
+ windowEnumerator = windows.reverseObjectEnumerator;
+
+ for (NSWindow *window in windowEnumerator) {
+ // We're meddling with normal and floating windows, so leave others alone
+ if (!(window.level == NSNormalWindowLevel || window.level == NSFloatingWindowLevel))
+ continue;
+
+ // Windows that hide automatically will keep their NSFloatingWindowLevel,
+ // and hence be on top of the window stack. We don't want to affect these
+ // windows, as otherwise we might end up with key windows being ordered
+ // behind these auto-hidden windows when activating the application by
+ // clicking on a new tool window.
+ if (window.hidesOnDeactivate)
+ continue;
+
+ if ([window conformsToProtocol:@protocol(QNSWindowProtocol)]) {
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaNSWindow *>(window).platformWindow;
+ window.level = notification.name == NSApplicationWillResignActiveNotification ?
+ NSNormalWindowLevel : cocoaWindow->windowLevel(cocoaWindow->window()->flags());
}
- free(methods);
+
+ // The documentation says that "when a window enters a new level, it’s ordered
+ // in front of all its peers in that level", but that doesn't seem to be the
+ // case in practice. To keep the order correct after meddling with the window
+ // levels, we explicitly order each window to the front. Since we are iterating
+ // the windows in back-to-front order, this is okey. The call also triggers AppKit
+ // to re-evaluate the level in relation to windows from other applications,
+ // working around an issue where our tool windows would stay on top of other
+ // application windows if activation was transferred to another application by
+ // clicking on it instead of via the application switcher or Dock. Finally, we
+ // do this re-ordering for all windows (except auto-hiding ones), otherwise we would
+ // end up triggering a bug in AppKit where the tool windows would disappear behind
+ // the application window.
+ [window orderFront:sender];
}
+}
+
+@end
+
+@implementation QNSPanel
+#define QNSWINDOW_PROTOCOL_IMPLMENTATION 1
+#include "qnswindow.mm"
+#undef QNSWINDOW_PROTOCOL_IMPLMENTATION
+@end
+
+#else // QNSWINDOW_PROTOCOL_IMPLMENTATION
+
+// The following content is mixed in to the QNSWindow and QNSPanel classes via includes
+
+{
+ // Member variables
+ QPointer<QCocoaWindow> m_platformWindow;
+}
+
+- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style
+ backing:(NSBackingStoreType)backingStoreType defer:(BOOL)defer screen:(NSScreen *)screen
+ platformWindow:(QCocoaWindow*)window
+{
+ // Initializing the window will end up in [NSWindow _commonAwake], which calls many
+ // of the getters below. We need to set up the platform window reference first, so
+ // we can properly reflect the window's state during initialization.
+ m_platformWindow = window;
- free(protocols);
+ return [super initWithContentRect:contentRect styleMask:style backing:backingStoreType defer:defer screen:screen];
}
- (QCocoaWindow *)platformWindow
{
- return qnsview_cast(self.contentView).platformWindow;
+ return m_platformWindow;
}
- (NSString *)description
{
- NSMutableString *description = [NSMutableString stringWithString:qt_objcDynamicSuper()];
+ NSMutableString *description = [NSMutableString stringWithString:[super description]];
#ifndef QT_NO_DEBUG_STREAM
QString contentViewDescription;
@@ -142,16 +204,15 @@ static bool isMouseEvent(NSEvent *ev)
- (BOOL)canBecomeKeyWindow
{
- QCocoaWindow *pw = self.platformWindow;
- if (!pw)
+ if (!m_platformWindow)
return NO;
- if (pw->shouldRefuseKeyWindowAndFirstResponder())
+ if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder())
return NO;
if ([self isKindOfClass:[QNSPanel class]]) {
// Only tool or dialog windows should become key:
- Qt::WindowType type = pw->window()->type();
+ Qt::WindowType type = m_platformWindow->window()->type();
if (type == Qt::Tool || type == Qt::Dialog)
return YES;
@@ -170,8 +231,7 @@ static bool isMouseEvent(NSEvent *ev)
// Windows with a transient parent (such as combobox popup windows)
// cannot become the main window:
- QCocoaWindow *pw = self.platformWindow;
- if (!pw || pw->window()->transientParent())
+ if (!m_platformWindow || m_platformWindow->window()->transientParent())
canBecomeMain = NO;
return canBecomeMain;
@@ -179,21 +239,18 @@ static bool isMouseEvent(NSEvent *ev)
- (BOOL)worksWhenModal
{
- if ([self isKindOfClass:[QNSPanel class]]) {
- if (QCocoaWindow *pw = self.platformWindow) {
- Qt::WindowType type = pw->window()->type();
- if (type == Qt::Popup || type == Qt::Dialog || type == Qt::Tool)
- return YES;
- }
+ if (m_platformWindow && [self isKindOfClass:[QNSPanel class]]) {
+ Qt::WindowType type = m_platformWindow->window()->type();
+ if (type == Qt::Popup || type == Qt::Dialog || type == Qt::Tool)
+ return YES;
}
- return qt_objcDynamicSuper();
+ return [super worksWhenModal];
}
- (BOOL)isOpaque
{
- return self.platformWindow ?
- self.platformWindow->isOpaque() : qt_objcDynamicSuper();
+ return m_platformWindow ? m_platformWindow->isOpaque() : [super isOpaque];
}
/*!
@@ -209,7 +266,7 @@ static bool isMouseEvent(NSEvent *ev)
- (NSColor *)backgroundColor
{
return self.styleMask == NSWindowStyleMaskBorderless
- ? [NSColor clearColor] : qt_objcDynamicSuper();
+ ? [NSColor clearColor] : [super backgroundColor];
}
- (void)sendEvent:(NSEvent*)theEvent
@@ -221,7 +278,7 @@ static bool isMouseEvent(NSEvent *ev)
// e.g. if being retained by other parts of AppKit, or in an auto-release
// pool. We guard against this in QNSView as well, as not all callbacks
// come via events, but if they do there's no point in propagating them.
- if (!self.platformWindow)
+ if (!m_platformWindow)
return;
// Prevent deallocation of this NSWindow during event delivery, as we
@@ -229,23 +286,22 @@ static bool isMouseEvent(NSEvent *ev)
[[self retain] autorelease];
const char *eventType = object_getClassName(theEvent);
- if (QWindowSystemInterface::handleNativeEvent(self.platformWindow->window(),
+ if (QWindowSystemInterface::handleNativeEvent(m_platformWindow->window(),
QByteArray::fromRawData(eventType, qstrlen(eventType)), theEvent, nullptr)) {
return;
}
- qt_objcDynamicSuper(theEvent);
+ [super sendEvent:theEvent];
- if (!self.platformWindow)
+ if (!m_platformWindow)
return; // Platform window went away while processing event
- QCocoaWindow *pw = self.platformWindow;
- if (pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
+ if (m_platformWindow->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
NSPoint loc = [theEvent locationInWindow];
NSRect windowFrame = [self convertRectFromScreen:self.frame];
NSRect contentFrame = self.contentView.frame;
if (NSMouseInRect(loc, windowFrame, NO) && !NSMouseInRect(loc, contentFrame, NO))
- [qnsview_cast(pw->view()) handleFrameStrutMouseEvent:theEvent];
+ [qnsview_cast(m_platformWindow->view()) handleFrameStrutMouseEvent:theEvent];
}
}
@@ -256,77 +312,12 @@ static bool isMouseEvent(NSEvent *ev)
[self release];
}
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
- (void)dealloc
{
qCDebug(lcQpaWindow) << "Deallocating" << self;
self.delegate = nil;
- qt_objcDynamicSuper();
-}
-#pragma clang diagnostic pop
-
-+ (void)applicationActivationChanged:(NSNotification*)notification
-{
- const id sender = self;
- NSEnumerator<NSWindow*> *windowEnumerator = nullptr;
- NSApplication *application = [NSApplication sharedApplication];
-
- // Unfortunately there's no NSWindowListOrderedBackToFront,
- // so we have to manually reverse the order using an array.
- NSMutableArray<NSWindow *> *windows = [NSMutableArray<NSWindow *> new];
- [application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
- usingBlock:^(NSWindow *window, BOOL *) {
- // For some reason AppKit will give us nil-windows, skip those
- if (!window)
- return;
-
- [windows addObject:window];
- }
- ];
-
- windowEnumerator = windows.reverseObjectEnumerator;
-
- for (NSWindow *window in windowEnumerator) {
- // We're meddling with normal and floating windows, so leave others alone
- if (!(window.level == NSNormalWindowLevel || window.level == NSFloatingWindowLevel))
- continue;
-
- // Windows that hide automatically will keep their NSFloatingWindowLevel,
- // and hence be on top of the window stack. We don't want to affect these
- // windows, as otherwise we might end up with key windows being ordered
- // behind these auto-hidden windows when activating the application by
- // clicking on a new tool window.
- if (window.hidesOnDeactivate)
- continue;
-
- if ([window conformsToProtocol:@protocol(QNSWindowProtocol)]) {
- QCocoaWindow *cocoaWindow = static_cast<QCocoaNSWindow *>(window).platformWindow;
- window.level = notification.name == NSApplicationWillResignActiveNotification ?
- NSNormalWindowLevel : cocoaWindow->windowLevel(cocoaWindow->window()->flags());
- }
-
- // The documentation says that "when a window enters a new level, it’s ordered
- // in front of all its peers in that level", but that doesn't seem to be the
- // case in practice. To keep the order correct after meddling with the window
- // levels, we explicitly order each window to the front. Since we are iterating
- // the windows in back-to-front order, this is okey. The call also triggers AppKit
- // to re-evaluate the level in relation to windows from other applications,
- // working around an issue where our tool windows would stay on top of other
- // application windows if activation was transferred to another application by
- // clicking on it instead of via the application switcher or Dock. Finally, we
- // do this re-ordering for all windows (except auto-hiding ones), otherwise we would
- // end up triggering a bug in AppKit where the tool windows would disappear behind
- // the application window.
- [window orderFront:sender];
- }
+ [super dealloc];
}
-@end
-
-@implementation QNSPanel
-// Implementation shared with QNSWindow, see +[QNSWindow load] above
-@end
-
-#undef super
+#endif