From fb00b4199e69b91b22d32c5f7e07cc10ed4ec781 Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Thu, 27 Apr 2017 15:08:01 -0400 Subject: OpenGL function lookup for QNX Qt no longer supports using OpenGL ES2 via static linkage. Task-number: QTBUG-60457 Change-Id: I754ff1c084ecdfdf7bea0bd691c8f0fc47a2fcb0 Reviewed-by: Dan Cape Reviewed-by: Laszlo Agocs --- src/plugins/platforms/qnx/qnx.pro | 2 +- src/plugins/platforms/qnx/qqnxglcontext.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index 0b052adf0f..34be6d582e 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -78,7 +78,7 @@ qtConfig(opengles2) { HEADERS += qqnxglcontext.h \ qqnxeglwindow.h - QMAKE_USE += egl + QMAKE_USE += opengl_es2 egl } CONFIG(qqnx_pps) { diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp index 0d3076a743..d35a4f0bba 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.cpp +++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp @@ -47,6 +47,8 @@ #include #include +#include + #if defined(QQNXGLCONTEXT_DEBUG) #define qGLContextDebug qDebug #else @@ -262,7 +264,10 @@ QFunctionPointer QQnxGLContext::getProcAddress(const char *procName) qFatal("QQNX: failed to set EGL API, err=%d", eglGetError()); // Lookup EGL extension function pointer - return static_cast(eglGetProcAddress(procName)); + QFunctionPointer result = static_cast(eglGetProcAddress(procName)); + if (!result) + result = reinterpret_cast(dlsym(RTLD_DEFAULT, procName)); + return result; } bool QQnxGLContext::isSharing() const -- cgit v1.2.3 From 3f1548ae82d4321b6fdbbf127dafbdf385374be0 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 4 May 2017 10:15:23 +0200 Subject: Restore behavior of using libEGL and libGLESv2 as default for angle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As Qt applications using OpenGL are linked against these libs, merging them into QtANGLE by default (780105f9062dec350bbe2a6800c40db3e6382578) was a binary incompatible change. This change restores the default behavior to the one before given change. If the user wants the libraries to be merged, he can pass combined-angle-lib to configure. Task-number: QTBUG-60373 Change-Id: Iedbd3f2ce9284fdde924cfae8d915d6d5fef00db Reviewed-by: Oswald Buddenhagen Reviewed-by: Friedemann Kleint Reviewed-by: Jan Arve Sæther Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/windows.pri | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 7d3ecc8aa2..73677311f5 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -1,6 +1,8 @@ # Note: OpenGL32 must precede Gdi32 as it overwrites some functions. LIBS += -lole32 -luser32 -lwinspool -limm32 -lwinmm -loleaut32 +QT_FOR_CONFIG += gui + qtConfig(opengl):!qtConfig(opengles2):!qtConfig(dynamicgl): LIBS *= -lopengl32 mingw: LIBS *= -luuid @@ -99,5 +101,10 @@ RESOURCES += $$PWD/openglblacklists.qrc qtConfig(accessibility): include($$PWD/accessible/accessible.pri) -DEFINES *= LIBEGL_NAME=$${LIBQTANGLE_NAME} -DEFINES *= LIBGLESV2_NAME=$${LIBQTANGLE_NAME} +qtConfig(combined-angle-lib) { + DEFINES *= LIBEGL_NAME=$${LIBQTANGLE_NAME} + DEFINES *= LIBGLESV2_NAME=$${LIBQTANGLE_NAME} +} else { + DEFINES *= LIBEGL_NAME=$${LIBEGL_NAME} + DEFINES *= LIBGLESV2_NAME=$${LIBGLESV2_NAME} +} -- cgit v1.2.3 From 329a029c361bcbaf70f3aa919693f0bef48a152f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 15 May 2017 09:12:37 +0200 Subject: Windows QPA: Do not raise/lower windows with Qt::WindowStaysOnTop/BottomHint Prospectively helps to fix Qt::WindowStaysOnTopHint not working reliably on Windows by preventing HWND_TOPMOST being cleared in raise(). Task-number: QTBUG-50271 Change-Id: I88f916a1cf8a2082236360b9eab874ad22b85762 Reviewed-by: Oliver Wolff Reviewed-by: Andy Shaw --- src/plugins/platforms/windows/qwindowswindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index d4effde52d..077511d4e1 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -870,13 +870,15 @@ void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other window void QWindowsBaseWindow::raise_sys() { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window(); - SetWindowPos(handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + if ((window()->flags() & (Qt::WindowStaysOnTopHint | Qt::WindowStaysOnBottomHint)) == 0) + SetWindowPos(handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } void QWindowsBaseWindow::lower_sys() { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window(); - SetWindowPos(handle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + if ((window()->flags() & (Qt::WindowStaysOnTopHint | Qt::WindowStaysOnBottomHint)) == 0) + SetWindowPos(handle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } void QWindowsBaseWindow::setWindowTitle_sys(const QString &title) -- cgit v1.2.3 From 7da9fa289068ed742307c6b921442365130e0818 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Sat, 13 May 2017 13:24:21 +0700 Subject: QCocoaMenuBar: Keep smart reference to platform window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib3a5b071f1cc66992969a85a092f8111e57dea44 Task-number: QTBUG-60786 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoamenubar.h | 2 +- src/plugins/platforms/cocoa/qcocoamenubar.mm | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h index 4870ca4103..0725e9db68 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.h +++ b/src/plugins/platforms/cocoa/qcocoamenubar.h @@ -83,7 +83,7 @@ private: QList > m_menus; NSMenu *m_nativeMenu; - QCocoaWindow *m_window; + QPointer m_window; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index a95ffc2f9f..82c405baa6 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -52,8 +52,7 @@ QT_BEGIN_NAMESPACE static QList static_menubars; -QCocoaMenuBar::QCocoaMenuBar() : - m_window(0) +QCocoaMenuBar::QCocoaMenuBar() { static_menubars.append(this); @@ -79,7 +78,7 @@ QCocoaMenuBar::~QCocoaMenuBar() [m_nativeMenu release]; static_menubars.removeOne(this); - if (m_window && m_window->menubar() == this) { + if (!m_window.isNull() && m_window->menubar() == this) { m_window->setMenubar(0); // Delete the children first so they do not cause @@ -92,9 +91,10 @@ QCocoaMenuBar::~QCocoaMenuBar() bool QCocoaMenuBar::needsImmediateUpdate() { - if (m_window && m_window->window()->isActive()) { - return true; - } else if (!m_window) { + if (!m_window.isNull()) { + if (m_window->window()->isActive()) + return true; + } else { // Only update if the focus/active window has no // menubar, which means it'll be using this menubar. // This is to avoid a modification in a parentless @@ -221,11 +221,11 @@ void QCocoaMenuBar::handleReparent(QWindow *newParentWindow) qDebug() << "QCocoaMenuBar" << this << "handleReparent" << newParentWindow; #endif - if (m_window) - m_window->setMenubar(NULL); + if (!m_window.isNull()) + m_window->setMenubar(nullptr); - if (newParentWindow == NULL) { - m_window = NULL; + if (newParentWindow == nullptr) { + m_window.clear(); } else { newParentWindow->create(); m_window = static_cast(newParentWindow->handle()); @@ -246,7 +246,7 @@ QCocoaWindow *QCocoaMenuBar::findWindowForMenubar() QCocoaMenuBar *QCocoaMenuBar::findGlobalMenubar() { foreach (QCocoaMenuBar *mb, static_menubars) { - if (mb->m_window == NULL) + if (mb->m_window.isNull()) return mb; } -- cgit v1.2.3 From b30ce069922b57656f58c531a5bec614f00a7fda Mon Sep 17 00:00:00 2001 From: Filipe Azevedo Date: Mon, 15 May 2017 22:13:25 +0200 Subject: iOS: Fix the shortcuts bar not correctly hidden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid a compiler warning due to a wrong Apple api, a wrong workaround was introduced. This caused the hide of the shortcuts as expects but the visual space reserved for shortcuts was still visible as at top with a height of ~55pixels. While this is not important because the default virtual keyboard is always shown, it become a problem when one want to introduce his own virtual keyboard (UIResponder.inputView) with no shortcuts bar. This fix really hide the shortcuts bar. Task-number: QTBUG-60812 Change-Id: I0da44dfc3fda15af3351543c0a05aac973b899b9 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index eab6792266..001985a128 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -242,11 +242,12 @@ if (platformData.value(kImePlatformDataHideShortcutsBar).toBool()) { // According to the docs, leadingBarButtonGroups/trailingBarButtonGroups should be set to nil to hide the shortcuts bar. // However, starting with iOS 10, the API has been surrounded with NS_ASSUME_NONNULL, which contradicts this and causes - // compiler warnings. And assigning just an empty array causes layout asserts. Hence, we assign empty button groups instead. - UIBarButtonItemGroup *leading = [[[UIBarButtonItemGroup alloc] initWithBarButtonItems:@[] representativeItem:nil] autorelease]; - UIBarButtonItemGroup *trailing = [[[UIBarButtonItemGroup alloc] initWithBarButtonItems:@[] representativeItem:nil] autorelease]; - self.inputAssistantItem.leadingBarButtonGroups = @[leading]; - self.inputAssistantItem.trailingBarButtonGroups = @[trailing]; + // compiler warnings. Still it is the way to go to really hide the space reserved for that. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + self.inputAssistantItem.leadingBarButtonGroups = nil; + self.inputAssistantItem.trailingBarButtonGroups = nil; +#pragma clang diagnostic pop } } #endif -- cgit v1.2.3 From b545a6359bd7a34ccb7683b871ccd4e1f197ae47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 12 May 2017 13:53:55 +0200 Subject: macOS: Don't create NSWindow for embedded views An embedded view does not have a QCocoaWindow parent, but that doesn't mean it's a top level. Improved debug logging to make issues related to this code easier to spot in the future. Change-Id: I15b5acdd8d7112600618465a3b65b64fddc306f7 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.mm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index b85fb97f67..5ff5d01a99 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -291,6 +291,8 @@ static void qt_closePopups() - (void)closeAndRelease { + qCDebug(lcQpaCocoaWindow) << "closeAndRelease" << self; + [self close]; if (self.helper.grabbingMouse) { @@ -361,6 +363,8 @@ static void qt_closePopups() - (void)closeAndRelease { + qCDebug(lcQpaCocoaWindow) << "closeAndRelease" << self; + [self.helper detachFromPlatformWindow]; [self close]; [self release]; @@ -1584,7 +1588,7 @@ void QCocoaWindow::recreateWindowIfNeeded() if (isChildNSWindow() != shouldBeChildNSWindow) recreateReason |= ChildNSWindowChanged; - const bool shouldBeContentView = !parentWindow || shouldBeChildNSWindow; + const bool shouldBeContentView = (!parentWindow && !m_viewIsEmbedded) || shouldBeChildNSWindow; if (isContentView() != shouldBeContentView) recreateReason |= ContentViewChanged; @@ -1601,7 +1605,7 @@ void QCocoaWindow::recreateWindowIfNeeded() return; } - qCDebug(lcQpaCocoaWindow) << "Recreating NSWindow due to" << recreateReason; + qCDebug(lcQpaCocoaWindow) << "Reconfiguring NSWindow due to" << recreateReason; QCocoaWindow *parentCocoaWindow = static_cast(parentWindow); @@ -1616,6 +1620,7 @@ void QCocoaWindow::recreateWindowIfNeeded() // Remove current window (if any) if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) { + qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow; [m_nsWindow closeAndRelease]; if (isChildNSWindow()) [m_view.window.parentWindow removeChildWindow:m_view.window]; @@ -1642,6 +1647,7 @@ void QCocoaWindow::recreateWindowIfNeeded() // Move view to new NSWindow if needed if (m_nsWindow.contentView != m_view) { + qCDebug(lcQpaCocoaWindow) << "Ensuring that view is content view for" << m_nsWindow; [m_view setPostsFrameChangedNotifications:NO]; [m_view retain]; if (m_view.superview) // m_view comes from another NSWindow @@ -1723,6 +1729,8 @@ void QCocoaWindow::requestActivateWindow() QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool shouldBePanel) { + qCDebug(lcQpaCocoaWindow) << "createNSWindow" << shouldBeChildNSWindow << shouldBePanel; + QMacAutoReleasePool pool; QRect rect = geometry(); -- cgit v1.2.3 From 9954187adba4d26a1b1aa93874993f15d6d8a0b9 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Sat, 13 May 2017 13:24:21 +0700 Subject: QCocoaMenuBar: Keep smart reference to platform window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib3a5b071f1cc66992969a85a092f8111e57dea44 Task-number: QTBUG-60786 Reviewed-by: Tor Arne Vestbø (cherry picked from commit 7da9fa289068ed742307c6b921442365130e0818) Reviewed-by: Erik Verbruggen --- src/plugins/platforms/cocoa/qcocoamenubar.h | 2 +- src/plugins/platforms/cocoa/qcocoamenubar.mm | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h index 4870ca4103..0725e9db68 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.h +++ b/src/plugins/platforms/cocoa/qcocoamenubar.h @@ -83,7 +83,7 @@ private: QList > m_menus; NSMenu *m_nativeMenu; - QCocoaWindow *m_window; + QPointer m_window; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index a95ffc2f9f..82c405baa6 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -52,8 +52,7 @@ QT_BEGIN_NAMESPACE static QList static_menubars; -QCocoaMenuBar::QCocoaMenuBar() : - m_window(0) +QCocoaMenuBar::QCocoaMenuBar() { static_menubars.append(this); @@ -79,7 +78,7 @@ QCocoaMenuBar::~QCocoaMenuBar() [m_nativeMenu release]; static_menubars.removeOne(this); - if (m_window && m_window->menubar() == this) { + if (!m_window.isNull() && m_window->menubar() == this) { m_window->setMenubar(0); // Delete the children first so they do not cause @@ -92,9 +91,10 @@ QCocoaMenuBar::~QCocoaMenuBar() bool QCocoaMenuBar::needsImmediateUpdate() { - if (m_window && m_window->window()->isActive()) { - return true; - } else if (!m_window) { + if (!m_window.isNull()) { + if (m_window->window()->isActive()) + return true; + } else { // Only update if the focus/active window has no // menubar, which means it'll be using this menubar. // This is to avoid a modification in a parentless @@ -221,11 +221,11 @@ void QCocoaMenuBar::handleReparent(QWindow *newParentWindow) qDebug() << "QCocoaMenuBar" << this << "handleReparent" << newParentWindow; #endif - if (m_window) - m_window->setMenubar(NULL); + if (!m_window.isNull()) + m_window->setMenubar(nullptr); - if (newParentWindow == NULL) { - m_window = NULL; + if (newParentWindow == nullptr) { + m_window.clear(); } else { newParentWindow->create(); m_window = static_cast(newParentWindow->handle()); @@ -246,7 +246,7 @@ QCocoaWindow *QCocoaMenuBar::findWindowForMenubar() QCocoaMenuBar *QCocoaMenuBar::findGlobalMenubar() { foreach (QCocoaMenuBar *mb, static_menubars) { - if (mb->m_window == NULL) + if (mb->m_window.isNull()) return mb; } -- cgit v1.2.3 From 3dd089c08b8faaecf51991f27b0360ceb7c6e1b1 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 11 May 2017 07:56:35 +0200 Subject: Cocoa: Clean up memory leak when providing the accessibilityActions Change-Id: Ib69155ceedb7bf35e3a7b5daa309fc2d54e3f254 Reviewed-by: Frederik Gladhorn --- src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 6001a845e8..7e6bae127c 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -509,7 +509,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of // actions - (NSArray *)accessibilityActionNames { - NSMutableArray * nsActions = [NSMutableArray new]; + NSMutableArray *nsActions = [[NSMutableArray new] autorelease]; QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); if (!iface || !iface->isValid()) return nsActions; -- cgit v1.2.3 From 4c346b6e2bfab976bc9b16275b8382aee38aefa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 29 Mar 2017 13:26:27 +0200 Subject: macOS: Don't keep WA_MacAlwaysShowToolWindow windows always on top On macOS if an application is no longer active then it will cause any tool windows to hide until the application is active again. For applications that did not want this behavior and thus wanted the tool window to stay visible, the WA_MacAlwaysShowToolWindow flag is available. In order to ensure that this flag is respected, the tool window needs to have its level changed when the application active status changes. Once it is no longer active the window needs to be seen as a normal window, and when it is active then it needs to be set to be a window that is always on top to get the right behavior. Due to various bugs in AppKit we need to explicitly order windows in front during this process, which requires us to then iterate the windows in back-to-front order. For macOS versions < 10.12 there is no way to get an ordered list of windows, so we fall back to using the window creation order. Task-number: QTBUG-57581 Change-Id: If20b4698616707685f83b1378f87593f8169c8c6 Reviewed-by: Andy Shaw --- src/plugins/platforms/cocoa/qcocoawindow.h | 1 + src/plugins/platforms/cocoa/qcocoawindow.mm | 84 ++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 567eb7438b..deba861fcc 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -302,6 +302,7 @@ public: // for QNSView friend class QCocoaBackingStore; friend class QCocoaNativeInterface; + bool alwaysShowToolWindow() const; void removeMonitor(); NSView *m_view; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 5ff5d01a99..59b76370ae 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -317,6 +317,71 @@ static void qt_closePopups() @synthesize helper = _helper; ++ (void)applicationActivationChanged:(NSNotification*)notification +{ + const id sender = self; + NSEnumerator *windowEnumerator = nullptr; + NSApplication *application = [NSApplication sharedApplication]; + +#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra) { + // Unfortunately there's no NSWindowListOrderedBackToFront, + // so we have to manually reverse the order using an array. + NSMutableArray *windows = [[[NSMutableArray alloc] init] autorelease]; + [application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack + usingBlock:^(NSWindow *window, BOOL *) { + // For some reason AppKit will give us nil-windows, skip those + if (!window) + return; + + [(NSMutableArray*)windows addObject:window]; + } + ]; + + windowEnumerator = windows.reverseObjectEnumerator; + } else +#endif + { + // No way to get ordered list of windows, so fall back to unordered, + // list, which typically corresponds to window creation order. + windowEnumerator = application.windows.objectEnumerator; + } + + 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>(window).helper.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]; + } +} + - (id)initWithContentRect:(NSRect)contentRect screen:(NSScreen*)screen styleMask:(NSUInteger)windowStyle @@ -330,6 +395,17 @@ static void qt_closePopups() if (self) { _helper = [[QNSWindowHelper alloc] initWithNSWindow:self platformWindow:qpw]; + + if (qpw->alwaysShowToolWindow()) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserver:[self class] selector:@selector(applicationActivationChanged:) + name:NSApplicationWillResignActiveNotification object:nil]; + [center addObserver:[self class] selector:@selector(applicationActivationChanged:) + name:NSApplicationWillBecomeActiveNotification object:nil]; + }); + } } return self; } @@ -1778,8 +1854,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool sh if (shouldBePanel) { // Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set - window.hidesOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && - !qt_mac_resolveOption(false, QPlatformWindow::window(), "_q_macAlwaysShowToolWindow", ""); + window.hidesOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && !alwaysShowToolWindow(); // Make popup windows show on the same desktop as the parent full-screen window window.collectionBehavior = NSWindowCollectionBehaviorFullScreenAuxiliary; @@ -1805,6 +1880,11 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool sh return window; } +bool QCocoaWindow::alwaysShowToolWindow() const +{ + return qt_mac_resolveOption(false, window(), "_q_macAlwaysShowToolWindow", ""); +} + void QCocoaWindow::removeMonitor() { if (!monitor) -- cgit v1.2.3