Implement QCocoaWindow::setWindowState.

Add window state change notification logic. Send
and expose event in addition to window state change
on window restore since the QWidget logic expects
this.

Modify QCocoaWindow::setVisible to sync up window
state that may have been set on the hidden window.

Refactor NSWindow event observing to use one observer
function for all notifications.

Add window state testing to tests/manual/windowflags
Add delay after showFullScreen in tst_qstatusbar to
wait for the Lion fullscreen transition.

Change-Id: I57c523cedd0644d4181b40d72046fad4fdb09a9c
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
Morten Johan Sorvig 2012-03-21 11:07:35 +01:00 committed by Qt by Nokia
parent 872f567d53
commit 128b7c56b7
10 changed files with 154 additions and 44 deletions

View File

@ -95,6 +95,7 @@ public:
void setCocoaGeometry(const QRect &rect); void setCocoaGeometry(const QRect &rect);
void setVisible(bool visible); void setVisible(bool visible);
Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
Qt::WindowState setWindowState(Qt::WindowState state);
void setWindowTitle(const QString &title); void setWindowTitle(const QString &title);
void raise(); void raise();
void lower(); void lower();
@ -129,6 +130,7 @@ protected:
QRect windowGeometry() const; QRect windowGeometry() const;
QCocoaWindow *parentCocoaWindow() const; QCocoaWindow *parentCocoaWindow() const;
void syncWindowState(Qt::WindowState newState);
// private: // private:
public: // for QNSView public: // for QNSView

View File

@ -165,15 +165,23 @@ void QCocoaWindow::setVisible(bool visible)
QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size())); QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
if (m_nsWindow) { if (m_nsWindow) {
if ([m_nsWindow canBecomeKeyWindow]) // setWindowState might have been called while the window was hidden and
[m_nsWindow makeKeyAndOrderFront:nil]; // will not change the NSWindow state in that case. Sync up here:
else syncWindowState(window()->windowState());
[m_nsWindow orderFront: nil];
if (window()->windowState() != Qt::WindowMinimized) {
if ([m_nsWindow canBecomeKeyWindow])
[m_nsWindow makeKeyAndOrderFront:nil];
else
[m_nsWindow orderFront: nil];
}
} }
} else { } else {
// qDebug() << "close" << this; // qDebug() << "close" << this;
if (m_nsWindow) if (m_nsWindow)
[m_nsWindow orderOut:m_nsWindow]; [m_nsWindow orderOut:m_nsWindow];
if (!QCoreApplication::closingDown())
QWindowSystemInterface::handleExposeEvent(window(), QRegion());
} }
} }
@ -183,6 +191,14 @@ Qt::WindowFlags QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
return m_windowFlags; return m_windowFlags;
} }
Qt::WindowState QCocoaWindow::setWindowState(Qt::WindowState state)
{
if ([m_nsWindow isVisible])
syncWindowState(state); // Window state set for hidden windows take effect when show() is called.
return state;
}
void QCocoaWindow::setWindowTitle(const QString &title) void QCocoaWindow::setWindowTitle(const QString &title)
{ {
QCocoaAutoReleasePool pool; QCocoaAutoReleasePool pool;
@ -446,27 +462,12 @@ void QCocoaWindow::setNSWindow(NSWindow *window)
// QCocoaWindow is deleted by Qt. // QCocoaWindow is deleted by Qt.
[window setReleasedWhenClosed : NO]; [window setReleasedWhenClosed : NO];
[[NSNotificationCenter defaultCenter] addObserver:m_contentView
selector:@selector(windowDidBecomeKey)
name:NSWindowDidBecomeKeyNotification
object:m_nsWindow];
[[NSNotificationCenter defaultCenter] addObserver:m_contentView [[NSNotificationCenter defaultCenter] addObserver:m_contentView
selector:@selector(windowDidResignKey) selector:@selector(windowNotification:)
name:NSWindowDidResignKeyNotification name:nil // Get all notifications
object:m_nsWindow]; object:m_nsWindow];
[[NSNotificationCenter defaultCenter] addObserver:m_contentView
selector:@selector(windowDidBecomeMain)
name:NSWindowDidBecomeMainNotification
object:m_nsWindow];
[[NSNotificationCenter defaultCenter] addObserver:m_contentView
selector:@selector(windowDidResignMain)
name:NSWindowDidResignMainNotification
object:m_nsWindow];
// ### Accept touch events by default. // ### Accept touch events by default.
// Beware that enabling touch events has a negative impact on the overall performance. // Beware that enabling touch events has a negative impact on the overall performance.
// We probably need a QWindowSystemInterface API to enable/disable touch events. // We probably need a QWindowSystemInterface API to enable/disable touch events.
@ -503,6 +504,49 @@ QCocoaWindow *QCocoaWindow::parentCocoaWindow() const
return 0; return 0;
} }
// Syncs the NSWindow minimize/maximize/fullscreen state with the current QWindow state
void QCocoaWindow::syncWindowState(Qt::WindowState newState)
{
if (!m_nsWindow)
return;
switch (newState) {
case Qt::WindowMinimized:
[m_nsWindow performMiniaturize : m_nsWindow];
break;
case Qt::WindowMaximized:
[m_nsWindow performZoom : m_nsWindow];
break;
case Qt::WindowFullScreen:
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
[m_nsWindow toggleFullScreen : m_nsWindow];
} else {
qWarning("Not implemented: setWindowState WindowFullScreen");
}
#endif
break;
default:
// Undo current states
if ([m_nsWindow isMiniaturized])
[m_nsWindow deminiaturize : m_nsWindow];
if ([m_nsWindow isZoomed])
[m_nsWindow performZoom : m_nsWindow]; // toggles
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
if (window()->windowState() & Qt::WindowFullScreen)
[m_nsWindow toggleFullScreen : m_nsWindow];
} else {
qWarning("Not implemented: setWindowState WindowFullScreen");
}
#endif
break;
}
}
bool QCocoaWindow::setWindowModified(bool modified) bool QCocoaWindow::setWindowModified(bool modified)
{ {
if (!m_nsWindow) if (!m_nsWindow)

View File

@ -70,8 +70,7 @@ QT_END_NAMESPACE
- (void)setImage:(QImage *)image; - (void)setImage:(QImage *)image;
- (void)drawRect:(NSRect)dirtyRect; - (void)drawRect:(NSRect)dirtyRect;
- (void)updateGeometry; - (void)updateGeometry;
- (void)windowDidBecomeKey; - (void)windowNotification : (NSNotification *) windowNotification;
- (void)windowDidResignKey;
- (BOOL)isFlipped; - (BOOL)isFlipped;
- (BOOL)acceptsFirstResponder; - (BOOL)acceptsFirstResponder;

View File

@ -144,29 +144,40 @@ static QTouchDevice *touchDevice = 0;
QWindowSystemInterface::handleSynchronousGeometryChange(m_window, geo); QWindowSystemInterface::handleSynchronousGeometryChange(m_window, geo);
} }
- (void)windowDidBecomeKey - (void)windowNotification : (NSNotification *) windowNotification
{ {
if (!m_platformWindow->windowIsPopupType()) //qDebug() << "windowNotification" << QCFString::toQString([windowNotification name]);
QWindowSystemInterface::handleWindowActivated(m_window);
}
- (void)windowDidResignKey NSString *notificationName = [windowNotification name];
{ if (notificationName == NSWindowDidBecomeKeyNotification) {
if (!m_platformWindow->windowIsPopupType()) if (!m_platformWindow->windowIsPopupType())
QWindowSystemInterface::handleWindowActivated(0); QWindowSystemInterface::handleWindowActivated(m_window);
} } else if (notificationName == NSWindowDidResignKeyNotification) {
if (!m_platformWindow->windowIsPopupType())
QWindowSystemInterface::handleWindowActivated(0);
} else if (notificationName == NSWindowDidMiniaturizeNotification) {
QWindowSystemInterface::handleWindowStateChanged(m_window, Qt::WindowMinimized);
} else if (notificationName == NSWindowDidDeminiaturizeNotification) {
QWindowSystemInterface::handleWindowStateChanged(m_window, Qt::WindowNoState);
// Qt expects an expose event after restore/deminiaturize. This also needs
// to be a non-synchronous event to make sure it gets processed after
// the state change event sent above.
QWindowSystemInterface::handleExposeEvent(m_window, QRegion(m_window->geometry()));
} else {
- (void)windowDidBecomeMain #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
{ if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
// qDebug() << "window did become main" << m_window; if (notificationName == NSWindowDidEnterFullScreenNotification) {
} QWindowSystemInterface::handleWindowStateChanged(m_window, Qt::WindowFullScreen);
} else if (notificationName == NSWindowDidExitFullScreenNotification) {
QWindowSystemInterface::handleWindowStateChanged(m_window, Qt::WindowNoState);
}
}
#endif
- (void)windowDidResignMain }
{
// qDebug() << "window did resign main" << m_window;
} }
- (void) setImage:(QImage *)image - (void) setImage:(QImage *)image
{ {
CGImageRelease(m_cgImage); CGImageRelease(m_cgImage);

View File

@ -199,7 +199,9 @@ void tst_QStatusBar::setSizeGripEnabled()
QVERIFY(!sizeGrip); QVERIFY(!sizeGrip);
qApp->processEvents(); qApp->processEvents();
#ifndef Q_OS_MAC // Work around Lion fullscreen issues on CI system - QTQAINFRA-506
mainWindow.showFullScreen(); mainWindow.showFullScreen();
#endif
#ifdef Q_WS_X11 #ifdef Q_WS_X11
qt_x11_wait_for_window_manager(&mainWindow); qt_x11_wait_for_window_manager(&mainWindow);
#endif #endif
@ -220,7 +222,9 @@ void tst_QStatusBar::setSizeGripEnabled()
QVERIFY(!sizeGrip->isVisible()); QVERIFY(!sizeGrip->isVisible());
qApp->processEvents(); qApp->processEvents();
#ifndef Q_OS_MAC
mainWindow.showNormal(); mainWindow.showNormal();
#endif
qApp->processEvents(); qApp->processEvents();
QTRY_VERIFY(sizeGrip->isVisible()); QTRY_VERIFY(sizeGrip->isVisible());
} }

View File

@ -62,6 +62,7 @@ ControllerWindow::ControllerWindow()
previewDialog = new PreviewDialog; previewDialog = new PreviewDialog;
createTypeGroupBox(); createTypeGroupBox();
createStateGroupBox();
createHintsGroupBox(); createHintsGroupBox();
quitButton = new QPushButton(tr("&Quit")); quitButton = new QPushButton(tr("&Quit"));
@ -73,6 +74,7 @@ ControllerWindow::ControllerWindow()
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(widgetTypeGroupBox); mainLayout->addWidget(widgetTypeGroupBox);
mainLayout->addWidget(windowStateGroupBox);
mainLayout->addWidget(additionalOptionsGroupBox); mainLayout->addWidget(additionalOptionsGroupBox);
mainLayout->addWidget(typeGroupBox); mainLayout->addWidget(typeGroupBox);
mainLayout->addWidget(hintsGroupBox); mainLayout->addWidget(hintsGroupBox);
@ -165,7 +167,17 @@ void ControllerWindow::updatePreview()
if (pos.y() < 0) if (pos.y() < 0)
pos.setY(0); pos.setY(0);
widget->move(pos); widget->move(pos);
widget->show();
Qt::WindowState windowState = Qt::WindowNoState;
if (minimizeButton->isChecked())
windowState = Qt::WindowMinimized;
else if (maximizeButton->isChecked())
windowState = Qt::WindowMaximized;
else if (fullscreenButton->isChecked())
windowState = Qt::WindowFullScreen;
widget->setWindowState(windowState);
widget->setVisible(visibleCheckBox->isChecked());
} }
void ControllerWindow::createTypeGroupBox() void ControllerWindow::createTypeGroupBox()
@ -212,6 +224,27 @@ void ControllerWindow::createTypeGroupBox()
} }
//! [5] //! [5]
void ControllerWindow::createStateGroupBox()
{
windowStateGroupBox = new QGroupBox(tr("Window State"));
visibleCheckBox = createCheckBox(tr("Visible"));
visibleCheckBox->setChecked(true);
restoreButton = createRadioButton(tr("Normal"));
restoreButton->setChecked(true);
minimizeButton = createRadioButton(tr("Minimized"));
maximizeButton = createRadioButton(tr("Maximized"));
fullscreenButton = createRadioButton(tr("Fullscreen"));;
QHBoxLayout *l = new QHBoxLayout;
l->addWidget(visibleCheckBox);
l->addWidget(restoreButton);
l->addWidget(minimizeButton);
l->addWidget(maximizeButton);
l->addWidget(fullscreenButton);
windowStateGroupBox->setLayout(l);
}
//! [6] //! [6]
void ControllerWindow::createHintsGroupBox() void ControllerWindow::createHintsGroupBox()
{ {

View File

@ -42,7 +42,7 @@
#ifndef CONTROLLERWINDOW_H #ifndef CONTROLLERWINDOW_H
#define CONTROLLERWINDOW_H #define CONTROLLERWINDOW_H
#include <QWidget> #include <QtWidgets/QWidget>
#include "previewwindow.h" #include "previewwindow.h"
@ -68,6 +68,7 @@ private slots:
private: private:
void createTypeGroupBox(); void createTypeGroupBox();
void createStateGroupBox();
void createHintsGroupBox(); void createHintsGroupBox();
QCheckBox *createCheckBox(const QString &text); QCheckBox *createCheckBox(const QString &text);
QRadioButton *createRadioButton(const QString &text); QRadioButton *createRadioButton(const QString &text);
@ -77,6 +78,7 @@ private:
PreviewDialog *previewDialog; PreviewDialog *previewDialog;
QGroupBox *widgetTypeGroupBox; QGroupBox *widgetTypeGroupBox;
QGroupBox *windowStateGroupBox;
QGroupBox *additionalOptionsGroupBox; QGroupBox *additionalOptionsGroupBox;
QGroupBox *typeGroupBox; QGroupBox *typeGroupBox;
QGroupBox *hintsGroupBox; QGroupBox *hintsGroupBox;
@ -87,6 +89,12 @@ private:
QCheckBox *modalWindowCheckBox; QCheckBox *modalWindowCheckBox;
QCheckBox *fixedSizeWindowCheckBox; QCheckBox *fixedSizeWindowCheckBox;
QCheckBox *visibleCheckBox;
QRadioButton *restoreButton;
QRadioButton *minimizeButton;
QRadioButton *maximizeButton;
QRadioButton *fullscreenButton;
QRadioButton *windowRadioButton; QRadioButton *windowRadioButton;
QRadioButton *dialogRadioButton; QRadioButton *dialogRadioButton;
QRadioButton *sheetRadioButton; QRadioButton *sheetRadioButton;

View File

@ -107,6 +107,8 @@ PreviewWindow::PreviewWindow(QWidget *parent)
showNormalButton = new QPushButton(tr("Show normal")); showNormalButton = new QPushButton(tr("Show normal"));
connect(showNormalButton, SIGNAL(clicked()), this, SLOT(showNormal())); connect(showNormalButton, SIGNAL(clicked()), this, SLOT(showNormal()));
showMinimizedButton = new QPushButton(tr("Show minimized"));
connect(showMinimizedButton, SIGNAL(clicked()), this, SLOT(showMinimized()));
showMaximizedButton = new QPushButton(tr("Show maximized")); showMaximizedButton = new QPushButton(tr("Show maximized"));
connect(showMaximizedButton, SIGNAL(clicked()), this, SLOT(showMaximized())); connect(showMaximizedButton, SIGNAL(clicked()), this, SLOT(showMaximized()));
showFullScreenButton = new QPushButton(tr("Show fullscreen")); showFullScreenButton = new QPushButton(tr("Show fullscreen"));
@ -115,6 +117,7 @@ PreviewWindow::PreviewWindow(QWidget *parent)
QVBoxLayout *layout = new QVBoxLayout; QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit); layout->addWidget(textEdit);
layout->addWidget(showNormalButton); layout->addWidget(showNormalButton);
layout->addWidget(showMinimizedButton);
layout->addWidget(showMaximizedButton); layout->addWidget(showMaximizedButton);
layout->addWidget(showFullScreenButton); layout->addWidget(showFullScreenButton);
layout->addWidget(closeButton); layout->addWidget(closeButton);
@ -143,6 +146,8 @@ PreviewDialog::PreviewDialog(QWidget *parent)
showNormalButton = new QPushButton(tr("Show normal")); showNormalButton = new QPushButton(tr("Show normal"));
connect(showNormalButton, SIGNAL(clicked()), this, SLOT(showNormal())); connect(showNormalButton, SIGNAL(clicked()), this, SLOT(showNormal()));
showMinimizedButton = new QPushButton(tr("Show minimized"));
connect(showMinimizedButton, SIGNAL(clicked()), this, SLOT(showMinimized()));
showMaximizedButton = new QPushButton(tr("Show maximized")); showMaximizedButton = new QPushButton(tr("Show maximized"));
connect(showMaximizedButton, SIGNAL(clicked()), this, SLOT(showMaximized())); connect(showMaximizedButton, SIGNAL(clicked()), this, SLOT(showMaximized()));
showFullScreenButton = new QPushButton(tr("Show fullscreen")); showFullScreenButton = new QPushButton(tr("Show fullscreen"));
@ -151,6 +156,7 @@ PreviewDialog::PreviewDialog(QWidget *parent)
QVBoxLayout *layout = new QVBoxLayout; QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit); layout->addWidget(textEdit);
layout->addWidget(showNormalButton); layout->addWidget(showNormalButton);
layout->addWidget(showMinimizedButton);
layout->addWidget(showMaximizedButton); layout->addWidget(showMaximizedButton);
layout->addWidget(showFullScreenButton); layout->addWidget(showFullScreenButton);
layout->addWidget(closeButton); layout->addWidget(closeButton);

View File

@ -42,8 +42,8 @@
#ifndef PREVIEWWINDOW_H #ifndef PREVIEWWINDOW_H
#define PREVIEWWINDOW_H #define PREVIEWWINDOW_H
#include <QWidget> #include <QtWidgets/QWidget>
#include <QDialog> #include <QtWidgets/QDialog>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QPushButton; class QPushButton;
@ -63,6 +63,7 @@ private:
QTextEdit *textEdit; QTextEdit *textEdit;
QPushButton *closeButton; QPushButton *closeButton;
QPushButton *showNormalButton; QPushButton *showNormalButton;
QPushButton *showMinimizedButton;
QPushButton *showMaximizedButton; QPushButton *showMaximizedButton;
QPushButton *showFullScreenButton; QPushButton *showFullScreenButton;
}; };
@ -80,6 +81,7 @@ private:
QTextEdit *textEdit; QTextEdit *textEdit;
QPushButton *closeButton; QPushButton *closeButton;
QPushButton *showNormalButton; QPushButton *showNormalButton;
QPushButton *showMinimizedButton;
QPushButton *showMaximizedButton; QPushButton *showMaximizedButton;
QPushButton *showFullScreenButton; QPushButton *showFullScreenButton;
}; };

View File

@ -5,3 +5,4 @@ HEADERS = controllerwindow.h \
SOURCES = controllerwindow.cpp \ SOURCES = controllerwindow.cpp \
previewwindow.cpp \ previewwindow.cpp \
main.cpp main.cpp
QT += widgets