summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm7
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm16
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm34
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm53
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.mm8
10 files changed, 107 insertions, 50 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 0f99a414a0..990acd5301 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -298,7 +298,8 @@ bool hasValueAttribute(QAccessibleInterface *interface)
Q_ASSERT(interface);
const QAccessible::Role qtrole = interface->role();
if (qtrole == QAccessible::EditableText
- || interface->valueInterface()) {
+ || interface->valueInterface()
+ || interface->state().checkable) {
return true;
}
@@ -330,6 +331,10 @@ id getValueAttribute(QAccessibleInterface *interface)
return QCFString::toNSString(QString::number(valueInterface->currentValue().toDouble()));
}
+ if (interface->state().checkable) {
+ return [NSNumber numberWithInt: (interface->state().checked ? 1 : 0)];
+ }
+
return nil;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index bc98d002f0..0b674b8d2f 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -417,7 +417,23 @@
}
- (id)accessibilityFocusedUIElement {
- return NSAccessibilityUnignoredAncestor(self);
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+
+ if (!iface || !iface->isValid()) {
+ qWarning() << "FocusedUIElement for INVALID";
+ return nil;
+ }
+ QAccessibleInterface *childInterface = iface->focusChild();
+ if (childInterface) {
+ QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
+ // FIXME: parent could be wrong
+ QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithId:childAxid parent:self];
+ [accessibleElement autorelease];
+ return accessibleElement;
+ }
+
+ // no focus found
+ return nil;
}
@end
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 33d7dcbcf4..0274ed8201 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -163,6 +163,7 @@ public:
// The following variables help organizing modal sessions:
QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
bool currentExecIsNSAppRun;
+ bool modalSessionOnNSAppRun;
bool nsAppRunCalledByQt;
bool cleanupModalSessionsNeeded;
uint processEventsCalled;
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 91b631bff9..495a54cac4 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -721,7 +721,6 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
// setting currentModalSessionCached to zero, so that interrupt() calls
// [NSApp abortModal] if another modal session is currently running
Q_Q(QCocoaEventDispatcher);
- q->interrupt();
// Add a new, empty (null), NSModalSession to the stack.
// It will become active the next time QEventDispatcher::processEvents is called.
@@ -734,6 +733,12 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
cocoaModalSessionStack.push(info);
updateChildrenWorksWhenModal();
currentModalSessionCached = 0;
+ if (currentExecIsNSAppRun) {
+ modalSessionOnNSAppRun = true;
+ q->wakeUp();
+ } else {
+ q->interrupt();
+ }
}
void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
@@ -772,6 +777,7 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate()
runLoopTimerRef(0),
blockSendPostedEvents(false),
currentExecIsNSAppRun(false),
+ modalSessionOnNSAppRun(false),
nsAppRunCalledByQt(false),
cleanupModalSessionsNeeded(false),
processEventsCalled(0),
@@ -902,6 +908,14 @@ void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info)
// processEvents() was called "manually," ignore this source for now
d->maybeCancelWaitForMoreEvents();
return;
+ } else if (d->modalSessionOnNSAppRun) {
+ // We're about to spawn the 1st modal session on top of the main runloop.
+ // Instead of calling processPostedEvents(), which would need us stop
+ // NSApp, we just re-enter processEvents(). This is equivalent to calling
+ // QDialog::exec() except that it's done in a non-blocking way.
+ d->modalSessionOnNSAppRun = false;
+ d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents);
+ return;
}
d->processPostedEvents();
d->maybeCancelWaitForMoreEvents();
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 65a9f87e2d..412818ae47 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -316,11 +316,17 @@ QCocoaIntegration *QCocoaIntegration::instance()
*/
void QCocoaIntegration::updateScreens()
{
- NSArray *screens = [NSScreen screens];
+ NSArray *scrs = [NSScreen screens];
+ NSMutableArray *screens = [NSMutableArray arrayWithArray:scrs];
+ if ([screens count] == 0)
+ if ([NSScreen mainScreen])
+ [screens addObject:[NSScreen mainScreen]];
+ if ([screens count] == 0)
+ return;
QSet<QCocoaScreen*> remainingScreens = QSet<QCocoaScreen*>::fromList(mScreens);
QList<QPlatformScreen *> siblings;
for (uint i = 0; i < [screens count]; i++) {
- NSScreen* scr = [[NSScreen screens] objectAtIndex:i];
+ NSScreen* scr = [screens objectAtIndex:i];
CGDirectDisplayID dpy = [[[scr deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
// If this screen is a mirror and is not the primary one of the mirror set, ignore it.
if (CGDisplayIsInMirrorSet(dpy)) {
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 6e1f00eebe..b7a6a14d4a 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -183,6 +183,7 @@ public:
void windowWillMove();
void windowDidMove();
void windowDidResize();
+ void windowDidEndLiveResize();
bool windowShouldClose();
bool windowIsPopupType(Qt::WindowType type = Qt::Widget) const;
@@ -252,6 +253,7 @@ public: // for QNSView
QList<QCocoaWindow *> m_childWindows;
Qt::WindowFlags m_windowFlags;
+ bool m_effectivelyMaximized;
Qt::WindowState m_synchedWindowState;
Qt::WindowModality m_windowModality;
QPointer<QWindow> m_activePopupWindow;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index c7fba4eef0..b27e1b03db 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -352,6 +352,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_contentViewIsToBeEmbedded(false)
, m_parentCocoaWindow(0)
, m_isNSWindowChild(false)
+ , m_effectivelyMaximized(false)
, m_synchedWindowState(Qt::WindowActive)
, m_windowModality(Qt::NonModal)
, m_windowUnderMouse(false)
@@ -1164,6 +1165,14 @@ void QCocoaWindow::windowDidResize()
[m_qtView updateGeometry];
}
+void QCocoaWindow::windowDidEndLiveResize()
+{
+ if (m_synchedWindowState == Qt::WindowMaximized && ![m_nsWindow isZoomed]) {
+ m_effectivelyMaximized = false;
+ [m_qtView notifyWindowStateChanged:Qt::WindowNoState];
+ }
+}
+
bool QCocoaWindow::windowShouldClose()
{
bool accepted = false;
@@ -1436,7 +1445,6 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
{
if (!m_nsWindow)
return;
-
// if content view width or height is 0 then the window animations will crash so
// do nothing except set the new state
NSRect contentRect = [contentView() frame];
@@ -1446,9 +1454,7 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
return;
}
- if ((m_synchedWindowState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) {
- [m_nsWindow performZoom : m_nsWindow]; // toggles
- }
+ Qt::WindowState predictedState = newState;
if ((m_synchedWindowState & Qt::WindowMinimized) != (newState & Qt::WindowMinimized)) {
if (newState & Qt::WindowMinimized) {
@@ -1458,12 +1464,26 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
}
}
+ if ((m_synchedWindowState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized) || (m_effectivelyMaximized && newState == Qt::WindowNoState)) {
+ if ((m_synchedWindowState & Qt::WindowFullScreen) == (newState & Qt::WindowFullScreen)) {
+ [m_nsWindow performZoom : m_nsWindow]; // toggles
+ m_effectivelyMaximized = !m_effectivelyMaximized;
+ } else if (!(newState & Qt::WindowMaximized)) {
+ // it would be nice to change the target geometry that toggleFullScreen will animate toward
+ // but there is no known way, so the maximized state is not possible at this time
+ predictedState = static_cast<Qt::WindowState>(static_cast<int>(newState) | Qt::WindowMaximized);
+ m_effectivelyMaximized = true;
+ }
+ }
+
if ((m_synchedWindowState & Qt::WindowFullScreen) != (newState & Qt::WindowFullScreen)) {
bool fakeFullScreen = true;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
if (window()->flags() & Qt::WindowFullscreenButtonHint) {
fakeFullScreen = false;
+ if (m_effectivelyMaximized && m_synchedWindowState == Qt::WindowFullScreen)
+ predictedState = Qt::WindowMaximized;
[m_nsWindow toggleFullScreen : m_nsWindow];
}
}
@@ -1490,8 +1510,12 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
}
}
+#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
+ qDebug() << "QCocoaWindow::syncWindowState" << newState << "actual" << predictedState << "was" << m_synchedWindowState << "effectively maximized" << m_effectivelyMaximized;
+#endif
+
// New state is now the current synched state
- m_synchedWindowState = newState;
+ m_synchedWindowState = predictedState;
}
bool QCocoaWindow::setWindowModified(bool modified)
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 47081ab890..1197aa9148 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -281,6 +281,12 @@ static QTouchDevice *touchDevice = 0;
- (void)notifyWindowStateChanged:(Qt::WindowState)newState
{
+ // If the window was maximized, then fullscreen, then tried to go directly to "normal" state,
+ // this notification will say that it is "normal", but it will still look maximized, and
+ // if you called performZoom it would actually take it back to "normal".
+ // So we should say that it is maximized because it actually is.
+ if (newState == Qt::WindowNoState && m_platformWindow->m_effectivelyMaximized)
+ newState = Qt::WindowMaximized;
QWindowSystemInterface::handleWindowStateChanged(m_window, newState);
// We want to read the window state back from the window,
// but the event we just sent may be asynchronous.
@@ -346,6 +352,8 @@ static QTouchDevice *touchDevice = 0;
- (void)notifyWindowWillZoom:(BOOL)willZoom
{
Qt::WindowState newState = willZoom ? Qt::WindowMaximized : Qt::WindowNoState;
+ if (!willZoom)
+ m_platformWindow->m_effectivelyMaximized = false;
[self notifyWindowStateChanged:newState];
}
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
index a438950a55..31e3e343b9 100644
--- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
@@ -54,6 +54,15 @@
@implementation QNSView (QNSViewAccessibility)
+- (id)childAccessibleElement {
+ if (!m_window->accessibleRoot())
+ return nil;
+
+ QAccessible::Id childId = QAccessible::uniqueId(m_window->accessibleRoot());
+ QCocoaAccessibleElement *child = [QCocoaAccessibleElement createElementWithId: childId parent: self];
+ return [child autorelease];
+}
+
// The QNSView is a container that the user does not interact directly with:
// Remove it from the user-visible accessibility tree.
- (BOOL)accessibilityIsIgnored {
@@ -61,58 +70,22 @@
}
- (id)accessibilityAttributeValue:(NSString *)attribute {
-
// activate accessibility updates
QCocoaIntegration::instance()->accessibility()->setActive(true);
- if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
- if (m_window->accessibleRoot())
- return QCocoaAccessible::macRole(m_window->accessibleRoot());
- return NSAccessibilityUnknownRole;
- } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
- return NSAccessibilityRoleDescriptionForUIElement(self);
- } else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
- if (!m_window->accessibleRoot())
- return [super accessibilityAttributeValue:attribute];
- return QCocoaAccessible::unignoredChildren(self, m_window->accessibleRoot());
+ if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
+ return NSAccessibilityUnignoredChildrenForOnlyChild([self childAccessibleElement]);
} else {
return [super accessibilityAttributeValue:attribute];
}
}
- (id)accessibilityHitTest:(NSPoint)point {
- if (!m_window->accessibleRoot())
- return [super accessibilityHitTest:point];
-
- QAccessibleInterface *childInterface = m_window->accessibleRoot()->childAt(point.x, qt_mac_flipYCoordinate(point.y));
- // No child found, meaning we hit the NSView
- if (!childInterface) {
- return [super accessibilityHitTest:point];
- }
-
- // Hit a child, forward to child accessible interface.
- QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
- // FIXME: parent could be wrong
- QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithId:childAxid parent:self ];
- [accessibleElement autorelease];
- return [accessibleElement accessibilityHitTest:point];
+ return [[self childAccessibleElement] accessibilityHitTest: point];
}
- (id)accessibilityFocusedUIElement {
- if (!m_window->accessibleRoot())
- return [super accessibilityFocusedUIElement];
-
- QAccessibleInterface *childInterface = m_window->accessibleRoot()->focusChild();
- if (childInterface) {
- QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
- // FIXME: parent could be wrong
- QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithId:childAxid parent:self];
- [accessibleElement autorelease];
- return accessibleElement;
- }
-
- // should not happen
- return nil;
+ return [[self childAccessibleElement] accessibilityFocusedUIElement];
}
@end
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
index c9b3d69381..d9509098c6 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
@@ -75,6 +75,14 @@
}
}
+- (void)windowDidEndLiveResize:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ if (m_cocoaWindow) {
+ m_cocoaWindow->windowDidEndLiveResize();
+ }
+}
+
- (void)windowWillMove:(NSNotification *)notification
{
Q_UNUSED(notification);