summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoawindow.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoawindow.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm786
1 files changed, 393 insertions, 393 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 9b10c8b053..b79804fd0b 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -41,9 +41,6 @@
#include "qcocoascreen.h"
#include "qnswindowdelegate.h"
#include "qcocoaeventdispatcher.h"
-#ifndef QT_NO_OPENGL
-#include "qcocoaglcontext.h"
-#endif
#include "qcocoahelpers.h"
#include "qcocoanativeinterface.h"
#include "qnsview.h"
@@ -117,24 +114,19 @@ static void qRegisterNotificationCallbacks()
return;
}
- if (lcCocoaNotifications().isDebugEnabled()) {
- if (cocoaWindows.isEmpty()) {
- qCDebug(lcCocoaNotifications) << "Could not find forwarding target for" <<
- qPrintable(notificationName) << "from" << notification.object;
- } else {
- QVector<QCocoaWindow *> debugWindows;
- for (QCocoaWindow *cocoaWindow : cocoaWindows)
- debugWindows += cocoaWindow;
- qCDebug(lcCocoaNotifications) << "Forwarding" << qPrintable(notificationName) <<
- "to" << debugWindows;
- }
+ if (lcCocoaNotifications().isDebugEnabled() && !cocoaWindows.isEmpty()) {
+ QVector<QCocoaWindow *> debugWindows;
+ for (QCocoaWindow *cocoaWindow : cocoaWindows)
+ debugWindows += cocoaWindow;
+ qCDebug(lcCocoaNotifications) << "Forwarding" << qPrintable(notificationName) <<
+ "to" << debugWindows;
}
// FIXME: Could be a foreign window, look up by iterating top level QWindows
for (QCocoaWindow *cocoaWindow : cocoaWindows) {
if (!method.invoke(cocoaWindow, Qt::DirectConnection)) {
- qCWarning(lcQpaCocoaWindow) << "Failed to invoke NSNotification callback for"
+ qCWarning(lcQpaWindow) << "Failed to invoke NSNotification callback for"
<< notification.name << "on" << cocoaWindow;
}
}
@@ -148,9 +140,7 @@ const int QCocoaWindow::NoAlertRequest = -1;
QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
: QPlatformWindow(win)
, m_view(nil)
- , m_nsWindow(0)
- , m_viewIsEmbedded(false)
- , m_viewIsToBeEmbedded(false)
+ , m_nsWindow(nil)
, m_lastReportedWindowState(Qt::WindowNoState)
, m_windowModality(Qt::NonModal)
, m_windowUnderMouse(false)
@@ -158,10 +148,7 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
, m_inSetVisible(false)
, m_inSetGeometry(false)
, m_inSetStyleMask(false)
-#ifndef QT_NO_OPENGL
- , m_glContext(0)
-#endif
- , m_menubar(0)
+ , m_menubar(nullptr)
, m_needsInvalidateShadow(false)
, m_hasModalSession(false)
, m_frameStrutEventsEnabled(false)
@@ -173,7 +160,7 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
, m_topContentBorderThickness(0)
, m_bottomContentBorderThickness(0)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::QCocoaWindow" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::QCocoaWindow" << window();
if (nativeHandle) {
m_view = reinterpret_cast<NSView *>(nativeHandle);
@@ -183,41 +170,24 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
void QCocoaWindow::initialize()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::initialize" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::initialize" << window();
QMacAutoReleasePool pool;
- if (!m_view) {
+ if (!m_view)
m_view = [[QNSView alloc] initWithCocoaWindow:this];
- // Enable high-dpi OpenGL for retina displays. Enabling has the side
- // effect that Cocoa will start calling glViewport(0, 0, width, height),
- // overriding any glViewport calls in application code. This is usually not a
- // problem, except if the appilcation wants to have a "custom" viewport.
- // (like the hellogl example)
- if (window()->supportsOpenGL()) {
- BOOL enable = qt_mac_resolveOption(YES, window(), "_q_mac_wantsBestResolutionOpenGLSurface",
- "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
- [m_view setWantsBestResolutionOpenGLSurface:enable];
- // See also QCocoaGLContext::makeCurrent for software renderer workarounds.
- }
- BOOL enable = qt_mac_resolveOption(NO, window(), "_q_mac_wantsLayer",
- "QT_MAC_WANTS_LAYER");
- [m_view setWantsLayer:enable];
- }
setGeometry(initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight));
recreateWindowIfNeeded();
window()->setGeometry(geometry());
- if (window()->isTopLevel())
- setWindowIcon(window()->icon());
m_initialized = true;
}
QCocoaWindow::~QCocoaWindow()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::~QCocoaWindow" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::~QCocoaWindow" << window();
QMacAutoReleasePool pool;
[m_nsWindow makeFirstResponder:nil];
@@ -232,10 +202,16 @@ QCocoaWindow::~QCocoaWindow()
if (!isForeignWindow())
[[NSNotificationCenter defaultCenter] removeObserver:m_view];
- // While it is unlikely that this window will be in the popup stack
- // during deletetion we clear any pointers here to make sure.
- if (QCocoaIntegration::instance()) {
- QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
+ if (QCocoaIntegration *cocoaIntegration = QCocoaIntegration::instance()) {
+ // While it is unlikely that this window will be in the popup stack
+ // during deletetion we clear any pointers here to make sure.
+ cocoaIntegration->popupWindowStack()->removeAll(this);
+
+#if QT_CONFIG(vulkan)
+ auto vulcanInstance = cocoaIntegration->getCocoaVulkanInstance();
+ if (vulcanInstance)
+ vulcanInstance->destroySurface(m_vulkanSurface);
+#endif
}
[m_view release];
@@ -255,7 +231,7 @@ QSurfaceFormat QCocoaWindow::format() const
void QCocoaWindow::setGeometry(const QRect &rectIn)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setGeometry" << window() << rectIn;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setGeometry" << window() << rectIn;
QBoolBlocker inSetGeometry(m_inSetGeometry, true);
@@ -283,7 +259,7 @@ QRect QCocoaWindow::geometry() const
// QWindows that are embedded in a NSView hiearchy may be considered
// top-level from Qt's point of view but are not from Cocoa's point
// of view. Embedded QWindows get global (screen) geometry.
- if (m_viewIsEmbedded) {
+ if (isEmbedded()) {
NSPoint windowPoint = [m_view convertPoint:NSMakePoint(0, 0) toView:nil];
NSRect screenRect = [[m_view window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
NSPoint screenPoint = screenRect.origin;
@@ -297,12 +273,12 @@ QRect QCocoaWindow::geometry() const
void QCocoaWindow::setCocoaGeometry(const QRect &rect)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setCocoaGeometry" << window() << rect;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setCocoaGeometry" << window() << rect;
QMacAutoReleasePool pool;
QPlatformWindow::setGeometry(rect);
- if (m_viewIsEmbedded) {
+ if (isEmbedded()) {
if (!isForeignWindow()) {
[m_view setFrame:NSMakeRect(0, 0, rect.width(), rect.height())];
}
@@ -321,12 +297,12 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
void QCocoaWindow::setVisible(bool visible)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setVisible" << window() << visible;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setVisible" << window() << visible;
m_inSetVisible = true;
QMacAutoReleasePool pool;
- QCocoaWindow *parentCocoaWindow = 0;
+ QCocoaWindow *parentCocoaWindow = nullptr;
if (window()->transientParent())
parentCocoaWindow = static_cast<QCocoaWindow *>(window()->transientParent()->handle());
@@ -378,13 +354,13 @@ void QCocoaWindow::setVisible(bool visible)
} else if (window()->modality() != Qt::NonModal) {
// show the window as application modal
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
- Q_ASSERT(cocoaEventDispatcher != 0);
+ Q_ASSERT(cocoaEventDispatcher);
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
cocoaEventDispatcherPrivate->beginModalSession(window());
m_hasModalSession = true;
} else if ([m_view.window canBecomeKeyWindow]) {
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
- QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
+ QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = nullptr;
if (cocoaEventDispatcher)
cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
@@ -403,11 +379,12 @@ void QCocoaWindow::setVisible(bool visible)
if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) {
removeMonitor();
monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) {
- QPointF localPoint = QCocoaScreen::mapFromNative([NSEvent mouseLocation]);
- const auto button = e.type == NSEventTypeMouseMoved ? Qt::NoButton : cocoaButton2QtButton([e buttonNumber]);
- const auto eventType = e.type == NSEventTypeMouseMoved ? QEvent::MouseMove : QEvent::MouseButtonPress;
- QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint,
- Qt::MouseButtons(uint(NSEvent.pressedMouseButtons & 0xFFFF)), button, eventType);
+ const auto button = cocoaButton2QtButton(e);
+ const auto buttons = currentlyPressedMouseButtons();
+ const auto eventType = cocoaEvent2QtMouseEvent(e);
+ const auto globalPoint = QCocoaScreen::mapFromNative(NSEvent.mouseLocation);
+ const auto localPoint = window()->mapFromGlobal(globalPoint.toPoint());
+ QWindowSystemInterface::handleMouseEvent(window(), localPoint, globalPoint, buttons, button, eventType);
}];
}
}
@@ -420,12 +397,8 @@ void QCocoaWindow::setVisible(bool visible)
[m_view setHidden:NO];
} else {
// qDebug() << "close" << this;
-#ifndef QT_NO_OPENGL
- if (m_glContext)
- m_glContext->windowWasHidden();
-#endif
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
- QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
+ QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = nullptr;
if (cocoaEventDispatcher)
cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
if (isContentView()) {
@@ -493,7 +466,8 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags)
// Any "special" window should be in at least the same level as its parent.
if (type != Qt::Window) {
const QWindow * const transientParent = window()->transientParent();
- const QCocoaWindow * const transientParentWindow = transientParent ? static_cast<QCocoaWindow *>(transientParent->handle()) : 0;
+ const QCocoaWindow * const transientParentWindow = transientParent ?
+ static_cast<QCocoaWindow *>(transientParent->handle()) : nullptr;
if (transientParentWindow)
windowLevel = qMax([transientParentWindow->nativeWindow() level], windowLevel);
}
@@ -562,54 +536,283 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
{
- if (isContentView()) {
- // While setting style mask we can have handleGeometryChange calls on a content
- // view with null geometry, reporting an invalid coordinates as a result.
- m_inSetStyleMask = true;
- m_view.window.styleMask = windowStyleMask(flags);
- m_inSetStyleMask = false;
- m_view.window.level = this->windowLevel(flags);
-
- m_view.window.hasShadow = !(flags & Qt::NoDropShadowWindowHint);
-
- if (!(flags & Qt::FramelessWindowHint))
- setWindowTitle(window()->title());
-
- Qt::WindowType type = window()->type();
- if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
- NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior;
- if ((flags & Qt::WindowFullscreenButtonHint) || m_view.window.qt_fullScreen) {
- behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
- behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
- } else {
- behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
- behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
- }
- m_view.window.collectionBehavior = behavior;
+ if (!isContentView())
+ return;
+
+ // While setting style mask we can have handleGeometryChange calls on a content
+ // view with null geometry, reporting an invalid coordinates as a result.
+ m_inSetStyleMask = true;
+ m_view.window.styleMask = windowStyleMask(flags);
+ m_inSetStyleMask = false;
+
+ Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
+ if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
+ NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior;
+ if ((flags & Qt::WindowFullscreenButtonHint) || m_view.window.qt_fullScreen) {
+ behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
+ behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
+ } else {
+ behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
+ behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
}
- setWindowZoomButton(flags);
-
- // Make window ignore mouse events if WindowTransparentForInput is set.
- // Note that ignoresMouseEvents has a special initial state where events
- // are ignored (passed through) based on window transparency, and that
- // setting the property to false does not return us to that state. Instead,
- // this makes the window capture all mouse events. Take care to only
- // set the property if needed. FIXME: recreate window if needed or find
- // some other way to implement WindowTransparentForInput.
- bool ignoreMouse = flags & Qt::WindowTransparentForInput;
- if (m_view.window.ignoresMouseEvents != ignoreMouse)
- m_view.window.ignoresMouseEvents = ignoreMouse;
+ m_view.window.collectionBehavior = behavior;
}
- m_windowFlags = flags;
+ // Set styleMask and collectionBehavior before applying window level, as
+ // the window level change will trigger verification of the two properties.
+ m_view.window.level = this->windowLevel(flags);
+
+ m_view.window.hasShadow = !(flags & Qt::NoDropShadowWindowHint);
+
+ if (!(flags & Qt::FramelessWindowHint))
+ setWindowTitle(window()->title());
+
+ setWindowZoomButton(flags);
+
+ // Make window ignore mouse events if WindowTransparentForInput is set.
+ // Note that ignoresMouseEvents has a special initial state where events
+ // are ignored (passed through) based on window transparency, and that
+ // setting the property to false does not return us to that state. Instead,
+ // this makes the window capture all mouse events. Take care to only
+ // set the property if needed. FIXME: recreate window if needed or find
+ // some other way to implement WindowTransparentForInput.
+ bool ignoreMouse = flags & Qt::WindowTransparentForInput;
+ if (m_view.window.ignoresMouseEvents != ignoreMouse)
+ m_view.window.ignoresMouseEvents = ignoreMouse;
}
+// ----------------------- Window state -----------------------
+
+/*!
+ Changes the state of the NSWindow, going in/out of minimize/zoomed/fullscreen
+
+ When this is called from QWindow::setWindowState(), the QWindow state has not been
+ updated yet, so window()->windowState() will reflect the previous state that was
+ reported to QtGui.
+*/
void QCocoaWindow::setWindowState(Qt::WindowStates state)
{
if (window()->isVisible())
applyWindowState(state); // Window state set for hidden windows take effect when show() is called
}
+void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
+{
+ if (!isContentView())
+ return;
+
+ const Qt::WindowState currentState = windowState();
+ const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState);
+
+ if (newState == currentState)
+ return;
+
+ qCDebug(lcQpaWindow) << "Applying" << newState << "to" << window() << "in" << currentState;
+
+ const NSSize contentSize = m_view.frame.size;
+ if (contentSize.width <= 0 || contentSize.height <= 0) {
+ // If content view width or height is 0 then the window animations will crash so
+ // do nothing. We report the current state back to reflect the failed operation.
+ qWarning("invalid window content view size, check your window geometry");
+ handleWindowStateChanged(HandleUnconditionally);
+ return;
+ }
+
+ const NSWindow *nsWindow = m_view.window;
+
+ if (nsWindow.styleMask & NSUtilityWindowMask
+ && newState & (Qt::WindowMinimized | Qt::WindowFullScreen)) {
+ qWarning() << window()->type() << "windows can not be made" << newState;
+ handleWindowStateChanged(HandleUnconditionally);
+ return;
+ }
+
+ const id sender = nsWindow;
+
+ // First we need to exit states that can't transition directly to other states
+ switch (currentState) {
+ case Qt::WindowMinimized:
+ [nsWindow deminiaturize:sender];
+ Q_ASSERT_X(windowState() != Qt::WindowMinimized, "QCocoaWindow",
+ "[NSWindow deminiaturize:] is synchronous");
+ break;
+ case Qt::WindowFullScreen: {
+ toggleFullScreen();
+ // Exiting fullscreen is not synchronous, so we need to wait for the
+ // NSWindowDidExitFullScreenNotification before continuing to apply
+ // the new state.
+ return;
+ }
+ default:;
+ }
+
+ // Then we apply the new state if needed
+ if (newState == windowState())
+ return;
+
+ switch (newState) {
+ case Qt::WindowFullScreen:
+ toggleFullScreen();
+ break;
+ case Qt::WindowMaximized:
+ toggleMaximized();
+ break;
+ case Qt::WindowMinimized:
+ [nsWindow miniaturize:sender];
+ break;
+ case Qt::WindowNoState:
+ if (windowState() == Qt::WindowMaximized)
+ toggleMaximized();
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+}
+
+Qt::WindowState QCocoaWindow::windowState() const
+{
+ // FIXME: Support compound states (Qt::WindowStates)
+
+ NSWindow *window = m_view.window;
+ if (window.miniaturized)
+ return Qt::WindowMinimized;
+ if (window.qt_fullScreen)
+ return Qt::WindowFullScreen;
+ if ((window.zoomed && !isTransitioningToFullScreen())
+ || (m_lastReportedWindowState == Qt::WindowMaximized && isTransitioningToFullScreen()))
+ return Qt::WindowMaximized;
+
+ // Note: We do not report Qt::WindowActive, even if isActive()
+ // is true, as QtGui does not expect this window state to be set.
+
+ return Qt::WindowNoState;
+}
+
+void QCocoaWindow::toggleMaximized()
+{
+ const NSWindow *window = m_view.window;
+
+ // The NSWindow needs to be resizable, otherwise the window will
+ // not be possible to zoom back to non-zoomed state.
+ const bool wasResizable = window.styleMask & NSResizableWindowMask;
+ window.styleMask |= NSResizableWindowMask;
+
+ const id sender = window;
+ [window zoom:sender];
+
+ if (!wasResizable)
+ window.styleMask &= ~NSResizableWindowMask;
+}
+
+void QCocoaWindow::toggleFullScreen()
+{
+ const NSWindow *window = m_view.window;
+
+ // The window needs to have the correct collection behavior for the
+ // toggleFullScreen call to have an effect. The collection behavior
+ // will be reset in windowDidEnterFullScreen/windowDidLeaveFullScreen.
+ window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
+
+ const id sender = window;
+ [window toggleFullScreen:sender];
+}
+
+void QCocoaWindow::windowWillEnterFullScreen()
+{
+ if (!isContentView())
+ return;
+
+ // The NSWindow needs to be resizable, otherwise we'll end up with
+ // the normal window geometry, centered in the middle of the screen
+ // on a black background. The styleMask will be reset below.
+ m_view.window.styleMask |= NSResizableWindowMask;
+}
+
+bool QCocoaWindow::isTransitioningToFullScreen() const
+{
+ NSWindow *window = m_view.window;
+ return window.styleMask & NSFullScreenWindowMask && !window.qt_fullScreen;
+}
+
+void QCocoaWindow::windowDidEnterFullScreen()
+{
+ if (!isContentView())
+ return;
+
+ Q_ASSERT_X(m_view.window.qt_fullScreen, "QCocoaWindow",
+ "FullScreen category processes window notifications first");
+
+ // Reset to original styleMask
+ setWindowFlags(window()->flags());
+
+ handleWindowStateChanged();
+}
+
+void QCocoaWindow::windowWillExitFullScreen()
+{
+ if (!isContentView())
+ return;
+
+ // The NSWindow needs to be resizable, otherwise we'll end up with
+ // a weird zoom animation. The styleMask will be reset below.
+ m_view.window.styleMask |= NSResizableWindowMask;
+}
+
+void QCocoaWindow::windowDidExitFullScreen()
+{
+ if (!isContentView())
+ return;
+
+ Q_ASSERT_X(!m_view.window.qt_fullScreen, "QCocoaWindow",
+ "FullScreen category processes window notifications first");
+
+ // Reset to original styleMask
+ setWindowFlags(window()->flags());
+
+ Qt::WindowState requestedState = window()->windowState();
+
+ // Deliver update of QWindow state
+ handleWindowStateChanged();
+
+ if (requestedState != windowState() && requestedState != Qt::WindowFullScreen) {
+ // We were only going out of full screen as an intermediate step before
+ // progressing into the final step, so re-sync the desired state.
+ applyWindowState(requestedState);
+ }
+}
+
+void QCocoaWindow::windowDidMiniaturize()
+{
+ if (!isContentView())
+ return;
+
+ handleWindowStateChanged();
+}
+
+void QCocoaWindow::windowDidDeminiaturize()
+{
+ if (!isContentView())
+ return;
+
+ handleWindowStateChanged();
+}
+
+void QCocoaWindow::handleWindowStateChanged(HandleFlags flags)
+{
+ Qt::WindowState currentState = windowState();
+ if (!(flags & HandleUnconditionally) && currentState == m_lastReportedWindowState)
+ return;
+
+ qCDebug(lcQpaWindow) << "QCocoaWindow::handleWindowStateChanged" <<
+ m_lastReportedWindowState << "-->" << currentState;
+
+ QWindowSystemInterface::handleWindowStateChanged<QWindowSystemInterface::SynchronousDelivery>(
+ window(), currentState, m_lastReportedWindowState);
+ m_lastReportedWindowState = currentState;
+}
+
+// ------------------------------------------------------------
+
void QCocoaWindow::setWindowTitle(const QString &title)
{
if (!isContentView())
@@ -680,7 +883,7 @@ bool QCocoaWindow::isAlertState() const
void QCocoaWindow::raise()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::raise" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::raise" << window();
// ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm)
if (!isContentView())
@@ -705,7 +908,7 @@ void QCocoaWindow::raise()
void QCocoaWindow::lower()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::lower" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::lower" << window();
if (!isContentView())
return;
@@ -718,6 +921,22 @@ bool QCocoaWindow::isExposed() const
return !m_exposedRect.isEmpty();
}
+bool QCocoaWindow::isEmbedded() const
+{
+ // Child QWindows are not embedded
+ if (window()->parent())
+ return false;
+
+ // Top-level QWindows with non-Qt NSWindows are embedded
+ if (m_view.window)
+ return !([m_view.window isKindOfClass:[QNSWindow class]] ||
+ [m_view.window isKindOfClass:[QNSPanel class]]);
+
+ // The window has no QWindow parent but also no NSWindow,
+ // conservatively reuturn false.
+ return false;
+}
+
bool QCocoaWindow::isOpaque() const
{
// OpenGL surfaces can be ordered either above(default) or below the NSWindow.
@@ -737,7 +956,7 @@ void QCocoaWindow::propagateSizeHints()
if (!isContentView())
return;
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::propagateSizeHints" << window()
+ qCDebug(lcQpaWindow) << "QCocoaWindow::propagateSizeHints" << window()
<< "min:" << windowMinimumSize() << "max:" << windowMaximumSize()
<< "increment:" << windowSizeIncrement()
<< "base:" << windowBaseSize();
@@ -754,7 +973,7 @@ void QCocoaWindow::propagateSizeHints()
window.contentMaxSize = NSSizeFromCGSize(windowMaximumSize().toCGSize());
// The window may end up with a fixed size; in this case the zoom button should be disabled.
- setWindowZoomButton(m_windowFlags);
+ setWindowZoomButton(this->window()->flags());
// sizeIncrement is observed to take values of (-1, -1) and (0, 0) for windows that should be
// resizable and that have no specific size increment set. Cocoa expects (1.0, 1.0) in this case.
@@ -771,7 +990,7 @@ void QCocoaWindow::propagateSizeHints()
void QCocoaWindow::setOpacity(qreal level)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setOpacity" << level;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setOpacity" << level;
if (!isContentView())
return;
@@ -780,7 +999,7 @@ void QCocoaWindow::setOpacity(qreal level)
void QCocoaWindow::setMask(const QRegion &region)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMask" << window() << region;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setMask" << window() << region;
if (m_view.layer) {
if (!region.isEmpty()) {
@@ -803,18 +1022,12 @@ void QCocoaWindow::setMask(const QRegion &region)
// time, and so would not result in an updated backingstore.
m_needsInvalidateShadow = true;
[m_view setNeedsDisplay:YES];
-
- // FIXME: [NSWindow invalidateShadow] has no effect when in layer-backed mode,
- // so if the mask is changed after the initial mask is applied, it will not
- // result in any visual change to the shadow. This is an Apple bug, and there
- // may be ways to work around it, such as calling setFrame on the window to
- // trigger some internal invalidation, but that needs more research.
}
}
bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setKeyboardGrabEnabled" << window() << grab;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setKeyboardGrabEnabled" << window() << grab;
if (!isContentView())
return false;
@@ -826,7 +1039,7 @@ bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
bool QCocoaWindow::setMouseGrabEnabled(bool grab)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMouseGrabEnabled" << window() << grab;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setMouseGrabEnabled" << window() << grab;
if (!isContentView())
return false;
@@ -843,10 +1056,10 @@ WId QCocoaWindow::winId() const
void QCocoaWindow::setParent(const QPlatformWindow *parentWindow)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setParent" << window() << (parentWindow ? parentWindow->window() : 0);
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setParent" << window() << (parentWindow ? parentWindow->window() : 0);
// recreate the window for compatibility
- bool unhideAfterRecreate = parentWindow && !m_viewIsToBeEmbedded && ![m_view isHidden];
+ bool unhideAfterRecreate = parentWindow && !isEmbedded() && ![m_view isHidden];
recreateWindowIfNeeded();
if (unhideAfterRecreate)
[m_view setHidden:NO];
@@ -863,9 +1076,8 @@ NSWindow *QCocoaWindow::nativeWindow() const
return m_view.window;
}
-void QCocoaWindow::setEmbeddedInForeignView(bool embedded)
+void QCocoaWindow::setEmbeddedInForeignView()
{
- m_viewIsToBeEmbedded = embedded;
// Release any previosly created NSWindow.
[m_nsWindow closeAndRelease];
m_nsWindow = 0;
@@ -948,8 +1160,8 @@ void QCocoaWindow::windowDidBecomeKey()
QWindowSystemInterface::handleEnterEvent(m_enterLeaveTargetWindow, windowPoint, screenPoint);
}
- if (!windowIsPopupType() && !qnsview_cast(m_view).isMenuView)
- QWindowSystemInterface::handleWindowActivated(window());
+ if (!windowIsPopupType())
+ QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(window());
}
void QCocoaWindow::windowDidResignKey()
@@ -966,82 +1178,8 @@ void QCocoaWindow::windowDidResignKey()
NSWindow *keyWindow = [NSApp keyWindow];
if (!keyWindow || keyWindow == m_view.window) {
// No new key window, go ahead and set the active window to zero
- if (!windowIsPopupType() && !qnsview_cast(m_view).isMenuView)
- QWindowSystemInterface::handleWindowActivated(0);
- }
-}
-
-void QCocoaWindow::windowDidMiniaturize()
-{
- if (!isContentView())
- return;
-
- handleWindowStateChanged();
-}
-
-void QCocoaWindow::windowDidDeminiaturize()
-{
- if (!isContentView())
- return;
-
- handleWindowStateChanged();
-}
-
-void QCocoaWindow::windowWillEnterFullScreen()
-{
- if (!isContentView())
- return;
-
- // The NSWindow needs to be resizable, otherwise we'll end up with
- // the normal window geometry, centered in the middle of the screen
- // on a black background. The styleMask will be reset below.
- m_view.window.styleMask |= NSResizableWindowMask;
-}
-
-void QCocoaWindow::windowDidEnterFullScreen()
-{
- if (!isContentView())
- return;
-
- Q_ASSERT_X(m_view.window.qt_fullScreen, "QCocoaWindow",
- "FullScreen category processes window notifications first");
-
- // Reset to original styleMask
- setWindowFlags(m_windowFlags);
-
- handleWindowStateChanged();
-}
-
-void QCocoaWindow::windowWillExitFullScreen()
-{
- if (!isContentView())
- return;
-
- // The NSWindow needs to be resizable, otherwise we'll end up with
- // a weird zoom animation. The styleMask will be reset below.
- m_view.window.styleMask |= NSResizableWindowMask;
-}
-
-void QCocoaWindow::windowDidExitFullScreen()
-{
- if (!isContentView())
- return;
-
- Q_ASSERT_X(!m_view.window.qt_fullScreen, "QCocoaWindow",
- "FullScreen category processes window notifications first");
-
- // Reset to original styleMask
- setWindowFlags(m_windowFlags);
-
- Qt::WindowState requestedState = window()->windowState();
-
- // Deliver update of QWindow state
- handleWindowStateChanged();
-
- if (requestedState != windowState() && requestedState != Qt::WindowFullScreen) {
- // We were only going out of full screen as an intermediate step before
- // progressing into the final step, so re-sync the desired state.
- applyWindowState(requestedState);
+ if (!windowIsPopupType())
+ QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(0);
}
}
@@ -1068,8 +1206,24 @@ void QCocoaWindow::windowDidChangeScreen()
if (!window())
return;
- if (QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenForNSScreen(m_view.window.screen))
- QWindowSystemInterface::handleWindowScreenChanged(window(), cocoaScreen->screen());
+ const bool wasRunningDisplayLink = static_cast<QCocoaScreen *>(screen())->isRunningDisplayLink();
+
+ if (QCocoaScreen *newScreen = QCocoaIntegration::instance()->screenForNSScreen(m_view.window.screen)) {
+ if (newScreen == screen()) {
+ // Screen properties have changed. Will be handled by
+ // NSApplicationDidChangeScreenParametersNotification
+ // in QCocoaIntegration::updateScreens().
+ return;
+ }
+
+ qCDebug(lcQpaWindow) << window() << "moved to" << newScreen;
+ QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
+
+ if (hasPendingUpdateRequest() && wasRunningDisplayLink)
+ requestUpdate(); // Restart display-link on new screen
+ } else {
+ qCWarning(lcQpaWindow) << "Failed to get QCocoaScreen for" << m_view.window.screen;
+ }
}
void QCocoaWindow::windowWillClose()
@@ -1083,7 +1237,7 @@ void QCocoaWindow::windowWillClose()
bool QCocoaWindow::windowShouldClose()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::windowShouldClose" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::windowShouldClose" << window();
// This callback should technically only determine if the window
// should (be allowed to) close, but since our QPA API to determine
// that also involves actually closing the window we do both at the
@@ -1104,22 +1258,14 @@ void QCocoaWindow::handleGeometryChange()
if (!m_initialized)
return;
- // Don't send the geometry change if the QWindow is designated to be
- // embedded in a foreign view hierarchy but has not actually been
- // embedded yet - it's too early.
- if (m_viewIsToBeEmbedded && !m_viewIsEmbedded)
- return;
-
// It can happen that the current NSWindow is nil (if we are changing styleMask
// from/to borderless, and the content view is being re-parented), which results
// in invalid coordinates.
if (m_inSetStyleMask && !m_view.window)
return;
- const bool isEmbedded = m_viewIsToBeEmbedded || m_viewIsEmbedded;
-
QRect newGeometry;
- if (isContentView() && !isEmbedded) {
+ if (isContentView() && !isEmbedded()) {
// Content views are positioned at (0, 0) in the window, so we resolve via the window
CGRect contentRect = [m_view.window contentRectForFrameRect:m_view.window.frame];
@@ -1130,7 +1276,7 @@ void QCocoaWindow::handleGeometryChange()
newGeometry = QRectF::fromCGRect(m_view.frame).toRect();
}
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleGeometryChange" << window()
+ qCDebug(lcQpaWindow) << "QCocoaWindow::handleGeometryChange" << window()
<< "current" << geometry() << "new" << newGeometry;
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
@@ -1162,24 +1308,10 @@ void QCocoaWindow::handleExposeEvent(const QRegion &region)
m_exposedRect = QRect();
}
- qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed();
+ qCDebug(lcQpaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed();
QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), region);
}
-void QCocoaWindow::handleWindowStateChanged(HandleFlags flags)
-{
- Qt::WindowState currentState = windowState();
- if (!(flags & HandleUnconditionally) && currentState == m_lastReportedWindowState)
- return;
-
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleWindowStateChanged" <<
- m_lastReportedWindowState << "-->" << currentState;
-
- QWindowSystemInterface::handleWindowStateChanged<QWindowSystemInterface::SynchronousDelivery>(
- window(), currentState, m_lastReportedWindowState);
- m_lastReportedWindowState = currentState;
-}
-
// --------------------------------------------------------------------------
bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const
@@ -1192,18 +1324,6 @@ bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const
return ((type & Qt::Popup) == Qt::Popup);
}
-#ifndef QT_NO_OPENGL
-void QCocoaWindow::setCurrentContext(QCocoaGLContext *context)
-{
- m_glContext = context;
-}
-
-QCocoaGLContext *QCocoaWindow::currentContext() const
-{
- return m_glContext;
-}
-#endif
-
/*!
Checks if the window is the content view of its immediate NSWindow.
@@ -1230,6 +1350,7 @@ void QCocoaWindow::recreateWindowIfNeeded()
QPlatformWindow *parentWindow = QPlatformWindow::parent();
+ const bool isEmbeddedView = isEmbedded();
RecreationReasons recreateReason = RecreationNotNeeded;
QCocoaWindow *oldParentCocoaWindow = nullptr;
@@ -1246,7 +1367,7 @@ void QCocoaWindow::recreateWindowIfNeeded()
if (m_windowModality != window()->modality())
recreateReason |= WindowModalityChanged;
- const bool shouldBeContentView = !parentWindow && !(m_viewIsToBeEmbedded || m_viewIsEmbedded);
+ const bool shouldBeContentView = !parentWindow && !isEmbeddedView;
if (isContentView() != shouldBeContentView)
recreateReason |= ContentViewChanged;
@@ -1258,7 +1379,7 @@ void QCocoaWindow::recreateWindowIfNeeded()
if (isPanel != shouldBePanel)
recreateReason |= PanelChanged;
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window() << recreateReason;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window() << recreateReason;
if (recreateReason == RecreationNotNeeded)
return;
@@ -1268,33 +1389,28 @@ void QCocoaWindow::recreateWindowIfNeeded()
// Remove current window (if any)
if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) {
if (m_nsWindow) {
- qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow;
+ qCDebug(lcQpaWindow) << "Getting rid of existing window" << m_nsWindow;
if (m_nsWindow.observationInfo) {
- qCCritical(lcQpaCocoaWindow) << m_nsWindow << "has active key-value observers (KVO)!"
+ qCCritical(lcQpaWindow) << m_nsWindow << "has active key-value observers (KVO)!"
<< "These will stop working now that the window is recreated, and will result in exceptions"
<< "when the observers are removed. Break in QCocoaWindow::recreateWindowIfNeeded to debug.";
}
[m_nsWindow closeAndRelease];
- if (isContentView()) {
+ if (isContentView() && !isEmbeddedView) {
// We explicitly disassociate m_view from the window's contentView,
// as AppKit does not automatically do this in response to removing
// the view from the NSThemeFrame subview list, so we might end up
// with a NSWindow contentView pointing to a deallocated NSView.
m_view.window.contentView = nil;
}
- m_nsWindow = 0;
+ m_nsWindow = nil;
}
}
- if (shouldBeContentView) {
- bool noPreviousWindow = m_nsWindow == 0;
- QCocoaNSWindow *newWindow = nullptr;
- if (noPreviousWindow)
- newWindow = createNSWindow(shouldBePanel);
-
+ if (shouldBeContentView && !m_nsWindow) {
// Move view to new NSWindow if needed
- if (newWindow) {
- qCDebug(lcQpaCocoaWindow) << "Ensuring that" << m_view << "is content view for" << newWindow;
+ if (auto *newWindow = createNSWindow(shouldBePanel)) {
+ qCDebug(lcQpaWindow) << "Ensuring that" << m_view << "is content view for" << newWindow;
[m_view setPostsFrameChangedNotifications:NO];
[newWindow setContentView:m_view];
[m_view setPostsFrameChangedNotifications:YES];
@@ -1304,14 +1420,14 @@ void QCocoaWindow::recreateWindowIfNeeded()
}
}
- if (m_viewIsToBeEmbedded) {
+ if (isEmbeddedView) {
// An embedded window doesn't have its own NSWindow.
} else if (!parentWindow) {
// QPlatformWindow subclasses must sync up with QWindow on creation:
propagateSizeHints();
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
- setWindowFilePath(window()->filePath());
+ setWindowFilePath(window()->filePath()); // Also sets window icon
setWindowState(window()->windowState());
} else {
// Child windows have no NSWindow, link the NSViews instead.
@@ -1334,14 +1450,28 @@ void QCocoaWindow::recreateWindowIfNeeded()
// top-level QWindows may have an attached NSToolBar, call
// update function which will attach to the NSWindow.
- if (!parentWindow)
+ if (!parentWindow && !isEmbeddedView)
updateNSToolbar();
}
void QCocoaWindow::requestUpdate()
{
- qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::requestUpdate" << window();
- QPlatformWindow::requestUpdate();
+ const int swapInterval = format().swapInterval();
+ qCDebug(lcQpaDrawing) << "QCocoaWindow::requestUpdate" << window() << "swapInterval" << swapInterval;
+
+ if (swapInterval > 0) {
+ // Vsync is enabled, deliver via CVDisplayLink
+ static_cast<QCocoaScreen *>(screen())->requestUpdate();
+ } else {
+ // Fall back to the un-throttled timer-based callback
+ QPlatformWindow::requestUpdate();
+ }
+}
+
+void QCocoaWindow::deliverUpdateRequest()
+{
+ qCDebug(lcQpaDrawing) << "Delivering update request to" << window();
+ QPlatformWindow::deliverUpdateRequest();
}
void QCocoaWindow::requestActivateWindow()
@@ -1375,7 +1505,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
}
if (!targetScreen) {
- qCWarning(lcQpaCocoaWindow) << "Window position" << rect << "outside any known screen, using primary screen";
+ qCWarning(lcQpaWindow) << "Window position" << rect << "outside any known screen, using primary screen";
targetScreen = QGuiApplication::primaryScreen();
// AppKit will only reposition a window that's outside the target screen area if
// the window has a title bar. If left out, the window ends up with no screen.
@@ -1399,8 +1529,10 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
Q_ASSERT_X(nsWindow.screen == cocoaScreen->nativeScreen(), "QCocoaWindow",
"Resulting NSScreen should match the requested NSScreen");
- if (targetScreen != window()->screen())
- QWindowSystemInterface::handleWindowScreenChanged(window(), targetScreen);
+ if (targetScreen != window()->screen()) {
+ QWindowSystemInterface::handleWindowScreenChanged<
+ QWindowSystemInterface::SynchronousDelivery>(window(), targetScreen);
+ }
nsWindow.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this];
@@ -1473,138 +1605,6 @@ void QCocoaWindow::removeMonitor()
monitor = nil;
}
-/*!
- Applies the given state to the NSWindow, going in/out of minimize/zoomed/fullscreen
-
- When this is called from QWindow::setWindowState(), the QWindow state has not been
- updated yet, so window()->windowState() will reflect the previous state that was
- reported to QtGui.
-*/
-void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
-{
- if (!isContentView())
- return;
-
- const Qt::WindowState currentState = windowState();
- const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState);
-
- if (newState == currentState)
- return;
-
- const NSSize contentSize = m_view.frame.size;
- if (contentSize.width <= 0 || contentSize.height <= 0) {
- // If content view width or height is 0 then the window animations will crash so
- // do nothing. We report the current state back to reflect the failed operation.
- qWarning("invalid window content view size, check your window geometry");
- handleWindowStateChanged(HandleUnconditionally);
- return;
- }
-
- const NSWindow *nsWindow = m_view.window;
-
- if (nsWindow.styleMask & NSUtilityWindowMask
- && newState & (Qt::WindowMinimized | Qt::WindowFullScreen)) {
- qWarning() << window()->type() << "windows can not be made" << newState;
- handleWindowStateChanged(HandleUnconditionally);
- return;
- }
-
- const id sender = nsWindow;
-
- // First we need to exit states that can't transition directly to other states
- switch (currentState) {
- case Qt::WindowMinimized:
- [nsWindow deminiaturize:sender];
- Q_ASSERT_X(windowState() != Qt::WindowMinimized, "QCocoaWindow",
- "[NSWindow deminiaturize:] is synchronous");
- break;
- case Qt::WindowFullScreen: {
- toggleFullScreen();
- // Exiting fullscreen is not synchronous, so we need to wait for the
- // NSWindowDidExitFullScreenNotification before continuing to apply
- // the new state.
- return;
- }
- default:;
- }
-
- // Then we apply the new state if needed
- if (newState == windowState())
- return;
-
- switch (newState) {
- case Qt::WindowFullScreen:
- toggleFullScreen();
- break;
- case Qt::WindowMaximized:
- toggleMaximized();
- break;
- case Qt::WindowMinimized:
- [nsWindow miniaturize:sender];
- break;
- case Qt::WindowNoState:
- if (windowState() == Qt::WindowMaximized)
- toggleMaximized();
- break;
- default:
- Q_UNREACHABLE();
- }
-}
-
-void QCocoaWindow::toggleMaximized()
-{
- const NSWindow *window = m_view.window;
-
- // The NSWindow needs to be resizable, otherwise the window will
- // not be possible to zoom back to non-zoomed state.
- const bool wasResizable = window.styleMask & NSResizableWindowMask;
- window.styleMask |= NSResizableWindowMask;
-
- const id sender = window;
- [window zoom:sender];
-
- if (!wasResizable)
- window.styleMask &= ~NSResizableWindowMask;
-}
-
-void QCocoaWindow::toggleFullScreen()
-{
- const NSWindow *window = m_view.window;
-
- // The window needs to have the correct collection behavior for the
- // toggleFullScreen call to have an effect. The collection behavior
- // will be reset in windowDidEnterFullScreen/windowDidLeaveFullScreen.
- window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
-
- const id sender = window;
- [window toggleFullScreen:sender];
-}
-
-bool QCocoaWindow::isTransitioningToFullScreen() const
-{
- NSWindow *window = m_view.window;
- return window.styleMask & NSFullScreenWindowMask && !window.qt_fullScreen;
-}
-
-Qt::WindowState QCocoaWindow::windowState() const
-{
- // FIXME: Support compound states (Qt::WindowStates)
-
- NSWindow *window = m_view.window;
- if (window.miniaturized)
- return Qt::WindowMinimized;
- if (window.qt_fullScreen)
- return Qt::WindowFullScreen;
- if ((window.zoomed && !isTransitioningToFullScreen())
- || (m_lastReportedWindowState == Qt::WindowMaximized && isTransitioningToFullScreen()))
- return Qt::WindowMaximized;
-
- // Note: We do not report Qt::WindowActive, even if isActive()
- // is true, as QtGui does not expect this window state to be set.
-
- return Qt::WindowNoState;
-}
-
bool QCocoaWindow::setWindowModified(bool modified)
{
if (!isContentView())