Merge remote-tracking branch 'origin/release' into stable

Conflicts:
	configure

Change-Id: I0d31f23483ea67c4cac5af16014366e1ba5ac093
This commit is contained in:
Frederik Gladhorn 2013-11-20 17:16:59 +01:00
commit ff4ad44b69
22 changed files with 1124 additions and 1269 deletions

2030
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -285,13 +285,13 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << odir << ".deps/%.d: " << pwd << "/%.cpp\n\t"; t << odir << ".deps/%.d: " << pwd << "/%.cpp\n\t";
if(project->isActiveConfig("echo_depend_creation")) if(project->isActiveConfig("echo_depend_creation"))
t << "@echo Creating depend for $<\n\t"; t << "@echo Creating depend for $<\n\t";
t << mkdir_p_asstring("$(@D)") << "\n\t" t << mkdir_p_asstring("$(@D)", false) << "\n\t"
<< "@$(CXX) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@\n\n"; << "@$(CXX) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@\n\n";
t << odir << ".deps/%.d: " << pwd << "/%.c\n\t"; t << odir << ".deps/%.d: " << pwd << "/%.c\n\t";
if(project->isActiveConfig("echo_depend_creation")) if(project->isActiveConfig("echo_depend_creation"))
t << "@echo Creating depend for $<\n\t"; t << "@echo Creating depend for $<\n\t";
t << mkdir_p_asstring("$(@D)") << "\n\t" t << mkdir_p_asstring("$(@D)", false) << "\n\t"
<< "@$(CC) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@\n\n"; << "@$(CC) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@\n\n";
static const char * const src[] = { "SOURCES", "GENERATED_SOURCES", 0 }; static const char * const src[] = { "SOURCES", "GENERATED_SOURCES", 0 };
@ -804,7 +804,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
project->first("OBJECTS_DIR")) + ddir, project->first("OBJECTS_DIR")) + ddir,
Option::output_dir, Option::output_dir)); Option::output_dir, Option::output_dir));
t << "dist: \n\t" t << "dist: \n\t"
<< mkdir_p_asstring(ddir_c) << "\n\t" << mkdir_p_asstring(ddir_c, false) << "\n\t"
<< "$(COPY_FILE) --parents $(SOURCES) $(DIST) " << ddir_c << Option::dir_sep << " && "; << "$(COPY_FILE) --parents $(SOURCES) $(DIST) " << ddir_c << Option::dir_sep << " && ";
if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) { if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS"); const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");

View File

@ -63,64 +63,45 @@ void QAndroidPlatformMessageDialogHelper::exec()
static QString standardButtonText(int sbutton) static QString standardButtonText(int sbutton)
{ {
QString buttonText = 0;
switch (sbutton) { switch (sbutton) {
case QMessageDialogOptions::Ok: case QMessageDialogOptions::Ok:
buttonText = QObject::tr("OK"); return QAndroidPlatformMessageDialogHelper::tr("OK");
break;
case QMessageDialogOptions::Save: case QMessageDialogOptions::Save:
buttonText = QObject::tr("Save"); return QAndroidPlatformMessageDialogHelper::tr("Save");
break;
case QMessageDialogOptions::Open: case QMessageDialogOptions::Open:
buttonText = QObject::tr("Open"); return QAndroidPlatformMessageDialogHelper::tr("Open");
break;
case QMessageDialogOptions::Cancel: case QMessageDialogOptions::Cancel:
buttonText = QObject::tr("Cancel"); return QAndroidPlatformMessageDialogHelper::tr("Cancel");
break;
case QMessageDialogOptions::Close: case QMessageDialogOptions::Close:
buttonText = QObject::tr("Close"); return QAndroidPlatformMessageDialogHelper::tr("Close");
break;
case QMessageDialogOptions::Apply: case QMessageDialogOptions::Apply:
buttonText = QObject::tr("Apply"); return QAndroidPlatformMessageDialogHelper::tr("Apply");
break;
case QMessageDialogOptions::Reset: case QMessageDialogOptions::Reset:
buttonText = QObject::tr("Reset"); return QAndroidPlatformMessageDialogHelper::tr("Reset");
break;
case QMessageDialogOptions::Help: case QMessageDialogOptions::Help:
buttonText = QObject::tr("Help"); return QAndroidPlatformMessageDialogHelper::tr("Help");
break;
case QMessageDialogOptions::Discard: case QMessageDialogOptions::Discard:
buttonText = QObject::tr("Discard"); return QAndroidPlatformMessageDialogHelper::tr("Discard");
break;
case QMessageDialogOptions::Yes: case QMessageDialogOptions::Yes:
buttonText = QObject::tr("Yes"); return QAndroidPlatformMessageDialogHelper::tr("Yes");
break;
case QMessageDialogOptions::YesToAll: case QMessageDialogOptions::YesToAll:
buttonText = QObject::tr("Yes to All"); return QAndroidPlatformMessageDialogHelper::tr("Yes to All");
break;
case QMessageDialogOptions::No: case QMessageDialogOptions::No:
buttonText = QObject::tr("No"); return QAndroidPlatformMessageDialogHelper::tr("No");
break;
case QMessageDialogOptions::NoToAll: case QMessageDialogOptions::NoToAll:
buttonText = QObject::tr("No to All"); return QAndroidPlatformMessageDialogHelper::tr("No to All");
break;
case QMessageDialogOptions::SaveAll: case QMessageDialogOptions::SaveAll:
buttonText = QObject::tr("Save All"); return QAndroidPlatformMessageDialogHelper::tr("Save All");
break;
case QMessageDialogOptions::Abort: case QMessageDialogOptions::Abort:
buttonText = QObject::tr("Abort"); return QAndroidPlatformMessageDialogHelper::tr("Abort");
break;
case QMessageDialogOptions::Retry: case QMessageDialogOptions::Retry:
buttonText = QObject::tr("Retry"); return QAndroidPlatformMessageDialogHelper::tr("Retry");
break;
case QMessageDialogOptions::Ignore: case QMessageDialogOptions::Ignore:
buttonText = QObject::tr("Ignore"); return QAndroidPlatformMessageDialogHelper::tr("Ignore");
break;
case QMessageDialogOptions::RestoreDefaults: case QMessageDialogOptions::RestoreDefaults:
buttonText = QObject::tr("Restore Defaults"); return QAndroidPlatformMessageDialogHelper::tr("Restore Defaults");
break;
} // switch } // switch
return buttonText; return QString();
} }
bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags

View File

@ -47,6 +47,5 @@
@interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate> @interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) QIOSViewController *qiosViewController;
@end @end

View File

@ -49,7 +49,6 @@
@implementation QIOSApplicationDelegate @implementation QIOSApplicationDelegate
@synthesize window; @synthesize window;
@synthesize qiosViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ {
@ -57,8 +56,7 @@
Q_UNUSED(launchOptions); Q_UNUSED(launchOptions);
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.qiosViewController = [[[QIOSViewController alloc] init] autorelease]; self.window.rootViewController = [[[QIOSViewController alloc] init] autorelease];
self.window.rootViewController = self.qiosViewController;
self.window.hidden = NO; self.window.hidden = NO;
@ -67,7 +65,6 @@
- (void)dealloc - (void)dealloc
{ {
[qiosViewController release];
[window release]; [window release];
[super dealloc]; [super dealloc];
} }

View File

@ -52,7 +52,6 @@ QT_BEGIN_NAMESPACE
class QPlatformScreen; class QPlatformScreen;
bool isQtApplication(); bool isQtApplication();
QIOSViewController *qiosViewController();
CGRect toCGRect(const QRect &rect); CGRect toCGRect(const QRect &rect);
QRect fromCGRect(const CGRect &rect); QRect fromCGRect(const CGRect &rect);

View File

@ -58,17 +58,6 @@ bool isQtApplication()
return isQt; return isQt;
} }
QIOSViewController *qiosViewController()
{
// If Qt controls the application, we have created a root view controller were we place top-level
// QWindows. Note that in a mixed native application, our view controller might later be removed or
// added as a child of another controller. To protect against that, we keep an explicit pointer to the
// view controller in cases where this is the controller we need to access.
static QIOSViewController *c = isQtApplication() ?
static_cast<QIOSApplicationDelegate *>([UIApplication sharedApplication].delegate).qiosViewController : nil;
return c;
}
CGRect toCGRect(const QRect &rect) CGRect toCGRect(const QRect &rect)
{ {
return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());

View File

@ -72,13 +72,14 @@ public:
UIScreen *uiScreen() const; UIScreen *uiScreen() const;
void setPrimaryOrientation(Qt::ScreenOrientation orientation); void updateProperties();
private: private:
UIScreen *m_uiScreen; UIScreen *m_uiScreen;
QRect m_geometry; QRect m_geometry;
QRect m_availableGeometry; QRect m_availableGeometry;
int m_depth; int m_depth;
uint m_unscaledDpi;
QSizeF m_physicalSize; QSizeF m_physicalSize;
QIOSOrientationListener *m_orientationListener; QIOSOrientationListener *m_orientationListener;
}; };

View File

@ -132,25 +132,14 @@ QIOSScreen::QIOSScreen(unsigned int screenIndex)
m_depth = 24; m_depth = 24;
} }
int unscaledDpi = 163; // Regular iPhone DPI
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
&& !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) { && !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) {
unscaledDpi = 132; m_unscaledDpi = 132;
}; } else {
m_unscaledDpi = 163; // Regular iPhone DPI
CGRect bounds = [m_uiScreen bounds];
m_geometry = QRect(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
CGRect frame = m_uiScreen.applicationFrame;
m_availableGeometry = QRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
const qreal millimetersPerInch = 25.4;
m_physicalSize = QSizeF(m_geometry.size()) / unscaledDpi * millimetersPerInch;
if (isQtApplication()) {
// When in a non-mixed environment, let QScreen follow the current interface orientation:
setPrimaryOrientation(toQtScreenOrientation(UIDeviceOrientation(qiosViewController().interfaceOrientation)));
} }
updateProperties();
} }
QIOSScreen::~QIOSScreen() QIOSScreen::~QIOSScreen()
@ -158,6 +147,44 @@ QIOSScreen::~QIOSScreen()
[m_orientationListener release]; [m_orientationListener release];
} }
void QIOSScreen::updateProperties()
{
UIWindow *uiWindow = 0;
for (uiWindow in [[UIApplication sharedApplication] windows]) {
if (uiWindow.screen == m_uiScreen)
break;
}
bool inPortrait = UIInterfaceOrientationIsPortrait(uiWindow.rootViewController.interfaceOrientation);
QRect geometry = inPortrait ? fromCGRect(m_uiScreen.bounds)
: QRect(m_uiScreen.bounds.origin.x, m_uiScreen.bounds.origin.y,
m_uiScreen.bounds.size.height, m_uiScreen.bounds.size.width);
if (geometry != m_geometry) {
m_geometry = geometry;
const qreal millimetersPerInch = 25.4;
m_physicalSize = QSizeF(m_geometry.size()) / m_unscaledDpi * millimetersPerInch;
QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry);
}
QRect availableGeometry = geometry;
CGSize applicationFrameSize = m_uiScreen.applicationFrame.size;
int statusBarHeight = geometry.height() - (inPortrait ? applicationFrameSize.height : applicationFrameSize.width);
availableGeometry.adjust(0, statusBarHeight, 0, 0);
if (availableGeometry != m_availableGeometry) {
m_availableGeometry = availableGeometry;
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_availableGeometry);
}
if (screen())
resizeMaximizedWindows();
}
QRect QIOSScreen::geometry() const QRect QIOSScreen::geometry() const
{ {
return m_geometry; return m_geometry;
@ -195,7 +222,9 @@ qreal QIOSScreen::devicePixelRatio() const
Qt::ScreenOrientation QIOSScreen::nativeOrientation() const Qt::ScreenOrientation QIOSScreen::nativeOrientation() const
{ {
return Qt::PortraitOrientation; // A UIScreen stays in the native orientation, regardless of rotation
return m_uiScreen.bounds.size.width >= m_uiScreen.bounds.size.height ?
Qt::LandscapeOrientation : Qt::PortraitOrientation;
} }
Qt::ScreenOrientation QIOSScreen::orientation() const Qt::ScreenOrientation QIOSScreen::orientation() const
@ -213,28 +242,6 @@ void QIOSScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
} }
} }
void QIOSScreen::setPrimaryOrientation(Qt::ScreenOrientation orientation)
{
// Note that UIScreen never changes orientation, but QScreen should. To work around
// this, we let QIOSViewController call us whenever interface orientation changes, and
// use that as primary orientation. After all, the viewcontrollers geometry is what we
// place QWindows on top of. A problem with this approach is that QIOSViewController is
// not in use in a mixed environment, which results in no change to primary orientation.
// We see that as acceptable since Qt should most likely not interfere with orientation
// for that case anyway.
bool portrait = screen()->isPortrait(orientation);
if (portrait && m_geometry.width() < m_geometry.height())
return;
// Switching portrait/landscape means swapping width/height (and adjusting x/y):
m_geometry = QRect(0, 0, m_geometry.height(), m_geometry.width());
m_physicalSize = QSizeF(m_physicalSize.height(), m_physicalSize.width());
m_availableGeometry = fromPortraitToPrimary(fromCGRect(m_uiScreen.applicationFrame), this);
QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry);
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_availableGeometry);
}
UIScreen *QIOSScreen::uiScreen() const UIScreen *QIOSScreen::uiScreen() const
{ {
return m_uiScreen; return m_uiScreen;

View File

@ -62,19 +62,16 @@
return UIInterfaceOrientationMaskAll; return UIInterfaceOrientationMaskAll;
} }
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{ {
Q_UNUSED(duration); Q_UNUSED(duration);
Q_UNUSED(interfaceOrientation);
if (!QCoreApplication::instance()) if (!QCoreApplication::instance())
return; // FIXME: Store orientation for later (?) return; // FIXME: Store orientation for later (?)
Qt::ScreenOrientation orientation = toQtScreenOrientation(UIDeviceOrientation(toInterfaceOrientation));
if (orientation == -1)
return;
QIOSScreen *qiosScreen = static_cast<QIOSScreen *>(QGuiApplication::primaryScreen()->handle()); QIOSScreen *qiosScreen = static_cast<QIOSScreen *>(QGuiApplication::primaryScreen()->handle());
qiosScreen->setPrimaryOrientation(orientation); qiosScreen->updateProperties();
} }
@end @end

View File

@ -52,6 +52,7 @@ class QIOSWindow;
@interface UIView (QIOS) @interface UIView (QIOS)
@property(readonly) QWindow *qwindow; @property(readonly) QWindow *qwindow;
@property(readonly) UIViewController *viewController;
@end @end
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -105,7 +105,7 @@
CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer); CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
eaglLayer.opaque = TRUE; eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
// Set up text input // Set up text input
@ -168,7 +168,7 @@
QRect geometry = fromCGRect(self.frame); QRect geometry = fromCGRect(self.frame);
m_qioswindow->QPlatformWindow::setGeometry(geometry); m_qioswindow->QPlatformWindow::setGeometry(geometry);
QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), geometry); QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), geometry);
QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), geometry); QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), QRect(QPoint(), geometry.size()));
// If we have a new size here we need to resize the FBO's corresponding buffers, // If we have a new size here we need to resize the FBO's corresponding buffers,
// but we defer that to when the application calls makeCurrent. // but we defer that to when the application calls makeCurrent.
@ -348,6 +348,16 @@
return nil; return nil;
} }
- (UIViewController *)viewController
{
id responder = self;
while ((responder = [responder nextResponder])) {
if ([responder isKindOfClass:UIViewController.class])
return responder;
}
return nil;
}
@end @end
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -404,7 +414,7 @@ void QIOSWindow::setVisible(bool visible)
requestActivateWindow(); requestActivateWindow();
} else { } else {
// Activate top-most visible QWindow: // Activate top-most visible QWindow:
NSArray *subviews = qiosViewController().view.subviews; NSArray *subviews = m_view.viewController.view.subviews;
for (int i = int(subviews.count) - 1; i >= 0; --i) { for (int i = int(subviews.count) - 1; i >= 0; --i) {
UIView *view = [subviews objectAtIndex:i]; UIView *view = [subviews objectAtIndex:i];
if (!view.hidden) { if (!view.hidden) {
@ -438,19 +448,26 @@ void QIOSWindow::setWindowState(Qt::WindowState state)
// Perhaps setting QWindow to maximized should also mean that we'll show // Perhaps setting QWindow to maximized should also mean that we'll show
// the statusbar, and vice versa for fullscreen? // the statusbar, and vice versa for fullscreen?
if (state != Qt::WindowNoState)
m_normalGeometry = geometry();
switch (state) { switch (state) {
case Qt::WindowMaximized: case Qt::WindowNoState:
case Qt::WindowFullScreen: { setGeometry(m_normalGeometry);
// Since UIScreen does not take orientation into account when
// reporting geometry, we need to look at the top view instead:
CGSize fullscreenSize = m_view.window.rootViewController.view.bounds.size;
m_view.frame = CGRectMake(0, 0, fullscreenSize.width, fullscreenSize.height);
m_view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
break; }
default:
m_view.frame = toCGRect(m_normalGeometry);
m_view.autoresizingMask = UIViewAutoresizingNone;
break; break;
case Qt::WindowMaximized:
setGeometry(screen()->availableGeometry());
break;
case Qt::WindowFullScreen:
setGeometry(screen()->geometry());
break;
case Qt::WindowMinimized:
setGeometry(QRect());
break;
case Qt::WindowActive:
Q_UNREACHABLE();
default:
Q_UNREACHABLE();
} }
} }
@ -460,7 +477,12 @@ void QIOSWindow::setParent(const QPlatformWindow *parentWindow)
UIView *parentView = reinterpret_cast<UIView *>(parentWindow->winId()); UIView *parentView = reinterpret_cast<UIView *>(parentWindow->winId());
[parentView addSubview:m_view]; [parentView addSubview:m_view];
} else if (isQtApplication()) { } else if (isQtApplication()) {
[qiosViewController().view addSubview:m_view]; for (UIWindow *uiWindow in [[UIApplication sharedApplication] windows]) {
if (uiWindow.screen == static_cast<QIOSScreen *>(screen())->uiScreen()) {
[uiWindow.rootViewController.view addSubview:m_view];
break;
}
}
} }
} }
@ -469,12 +491,14 @@ void QIOSWindow::requestActivateWindow()
// Note that several windows can be active at the same time if they exist in the same // Note that several windows can be active at the same time if they exist in the same
// hierarchy (transient children). But only one window can be QGuiApplication::focusWindow(). // hierarchy (transient children). But only one window can be QGuiApplication::focusWindow().
// Dispite the name, 'requestActivateWindow' means raise and transfer focus to the window: // Dispite the name, 'requestActivateWindow' means raise and transfer focus to the window:
if (!window()->isTopLevel() || blockedByModal()) if (blockedByModal())
return; return;
[m_view.window makeKeyWindow]; [m_view.window makeKeyWindow];
raise(); if (window()->isTopLevel())
raise();
QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext(); QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
static_cast<QIOSInputContext *>(context)->focusViewChanged(m_view); static_cast<QIOSInputContext *>(context)->focusViewChanged(m_view);
QWindowSystemInterface::handleWindowActivated(window()); QWindowSystemInterface::handleWindowActivated(window());

View File

@ -53,6 +53,7 @@
#include <qpa/qplatformintegration.h> #include <qpa/qplatformintegration.h>
#include "QtGui/private/qwindow_p.h" #include "QtGui/private/qwindow_p.h"
#include "QtGui/private/qguiapplication_p.h" #include "QtGui/private/qguiapplication_p.h"
#include <private/qwindowcontainer_p.h>
#include <qpa/qplatformcursor.h> #include <qpa/qplatformcursor.h>
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
@ -267,8 +268,11 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
// Reparenting toplevel to child // Reparenting toplevel to child
if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
if (extra && extra->hasWindowContainer)
QWindowContainer::toplevelAboutToBeDestroyed(q);
q->destroy(); q->destroy();
}
adjustFlags(f, q); adjustFlags(f, q);
data.window_flags = f; data.window_flags = f;
@ -506,9 +510,9 @@ void QWidgetPrivate::show_sys()
QWindow *window = q->windowHandle(); QWindow *window = q->windowHandle();
q->setAttribute(Qt::WA_Mapped);
if (q->testAttribute(Qt::WA_DontShowOnScreen)) { if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
invalidateBuffer(q->rect()); invalidateBuffer(q->rect());
q->setAttribute(Qt::WA_Mapped);
if (q->isWindow() && q->windowModality() != Qt::NonModal && window) { if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
// add our window to the modal window list // add our window to the modal window list
QGuiApplicationPrivate::showModalWindow(window); QGuiApplicationPrivate::showModalWindow(window);

View File

@ -715,6 +715,10 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
break; break;
} }
// Note that widgetState == m_widget->data->window_state when triggered by QWidget::setWindowState().
if (!(widgetState & Qt::WindowMinimized))
m_widget->setAttribute(Qt::WA_Mapped);
// Sent event if the state changed (that is, it is not triggered by // Sent event if the state changed (that is, it is not triggered by
// QWidget::setWindowState(), which also sends an event to the widget). // QWidget::setWindowState(), which also sends an event to the widget).
if (widgetState != int(m_widget->data->window_state)) { if (widgetState != int(m_widget->data->window_state)) {

View File

@ -305,15 +305,28 @@ static void qwindowcontainer_traverse(QWidget *parent, qwindowcontainer_traverse
} }
} }
void QWindowContainer::toplevelAboutToBeDestroyed(QWidget *parent)
{
if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) {
d->window->setParent(&d->fakeParent);
}
qwindowcontainer_traverse(parent, toplevelAboutToBeDestroyed);
}
void QWindowContainer::parentWasChanged(QWidget *parent) void QWindowContainer::parentWasChanged(QWidget *parent)
{ {
if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) {
if (d->window->parent()) { if (d->window->parent()) {
d->updateUsesNativeWidgets(); d->updateUsesNativeWidgets();
d->markParentChain(); d->markParentChain();
d->window->setParent(d->usesNativeWidgets QWidget *toplevel = d->usesNativeWidgets ? parent : parent->window();
? parent->windowHandle() if (!toplevel->windowHandle()) {
: parent->window()->windowHandle()); QWidgetPrivate *tld = static_cast<QWidgetPrivate *>(QWidgetPrivate::get(toplevel));
tld->createTLExtra();
tld->createTLSysExtra();
Q_ASSERT(toplevel->windowHandle());
}
d->window->setParent(toplevel->windowHandle());
d->updateGeometry(); d->updateGeometry();
} }
} }

View File

@ -57,6 +57,7 @@ public:
explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = 0, Qt::WindowFlags f = 0); explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = 0, Qt::WindowFlags f = 0);
~QWindowContainer(); ~QWindowContainer();
static void toplevelAboutToBeDestroyed(QWidget *parent);
static void parentWasChanged(QWidget *parent); static void parentWasChanged(QWidget *parent);
static void parentWasMoved(QWidget *parent); static void parentWasMoved(QWidget *parent);
static void parentWasRaised(QWidget *parent); static void parentWasRaised(QWidget *parent);

View File

@ -1834,6 +1834,14 @@ QSize QMenu::sizeHint() const
void QMenu::popup(const QPoint &p, QAction *atAction) void QMenu::popup(const QPoint &p, QAction *atAction)
{ {
Q_D(QMenu); Q_D(QMenu);
#ifdef Q_OS_ANDROID
if (!d->platformMenu.isNull() && !testAttribute(Qt::WA_SetStyle)) {
d->platformMenu->showPopup(window()->windowHandle(), p, 0);
return;
}
#endif
if (d->scroll) { // reset scroll state from last popup if (d->scroll) { // reset scroll state from last popup
if (d->scroll->scrollOffset) if (d->scroll->scrollOffset)
d->itemsDirty = 1; // sizeHint will be incorrect if there is previous scroll d->itemsDirty = 1; // sizeHint will be incorrect if there is previous scroll

View File

@ -177,7 +177,7 @@ void tst_QWindow::resizeEventAfterResize()
Window window; Window window;
window.setGeometry(geometry); window.setGeometry(geometry);
window.show(); window.showNormal();
QTRY_COMPARE(window.received(QEvent::Resize), 1); QTRY_COMPARE(window.received(QEvent::Resize), 1);
@ -843,7 +843,10 @@ void tst_QWindow::activateAndClose()
{ {
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
QWindow window; QWindow window;
window.show(); // qWaitForWindowActive will block for the duration of
// of the timeout if the window is at 0,0
window.setGeometry(QGuiApplication::primaryScreen()->availableGeometry().adjusted(1, 1, -1, -1));
window.showNormal();
window.requestActivate(); window.requestActivate();
QVERIFY(QTest::qWaitForWindowActive(&window)); QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(qGuiApp->focusWindow(), &window); QCOMPARE(qGuiApp->focusWindow(), &window);

View File

@ -7192,6 +7192,10 @@ void tst_QWidget::hideOpaqueChildWhileHidden()
#if !defined(Q_OS_WINCE) #if !defined(Q_OS_WINCE)
void tst_QWidget::updateWhileMinimized() void tst_QWidget::updateWhileMinimized()
{ {
#ifdef Q_OS_UNIX
if (qgetenv("XDG_CURRENT_DESKTOP").contains("Unity"))
QSKIP("This test fails on Unity."); // Minimized windows are not unmapped for some reason.
#endif // Q_OS_UNIX
UpdateWidget widget; UpdateWidget widget;
// Filter out activation change and focus events to avoid update() calls in QWidget. // Filter out activation change and focus events to avoid update() calls in QWidget.
widget.updateOnActivationChangeAndFocusIn = false; widget.updateOnActivationChangeAndFocusIn = false;

View File

@ -91,6 +91,8 @@ private slots:
void tst_showWithoutActivating(); void tst_showWithoutActivating();
void tst_paintEventOnSecondShow(); void tst_paintEventOnSecondShow();
void obscuredNativeMapped();
#ifndef QT_NO_DRAGANDDROP #ifndef QT_NO_DRAGANDDROP
void tst_dnd(); void tst_dnd();
#endif #endif
@ -368,6 +370,32 @@ void tst_QWidget_window::tst_paintEventOnSecondShow()
QTRY_VERIFY(w.paintEventReceived); QTRY_VERIFY(w.paintEventReceived);
} }
// QTBUG-33520, a toplevel fully obscured by native children should still receive Qt::WA_Mapped
void tst_QWidget_window::obscuredNativeMapped()
{
enum { size = 200 };
QWidget topLevel;
topLevel.setWindowFlags(Qt::FramelessWindowHint);
QWidget *child = new QWidget(&topLevel);
child->resize(size, size);
topLevel.resize(size, size);
topLevel.move(QGuiApplication::primaryScreen()->availableGeometry().center() - QPoint(size /2 , size / 2));
child->winId();
topLevel.show();
QTRY_VERIFY(topLevel.testAttribute(Qt::WA_Mapped));
#if defined(Q_OS_MAC)
QSKIP("This test fails on Mac."); // Minimized windows are not unmapped for some reason.
#elif defined(Q_OS_UNIX)
if (qgetenv("XDG_CURRENT_DESKTOP").contains("Unity"))
QSKIP("This test fails on Unity."); // Minimized windows are not unmapped for some reason.
#endif // Q_OS_UNIX
topLevel.setWindowState(Qt::WindowMinimized);
QTRY_VERIFY(!topLevel.testAttribute(Qt::WA_Mapped));
topLevel.setWindowState(Qt::WindowNoState);
QTRY_VERIFY(topLevel.testAttribute(Qt::WA_Mapped));
}
#ifndef QT_NO_DRAGANDDROP #ifndef QT_NO_DRAGANDDROP
/* DnD test for QWidgetWindow (handleDrag*Event() functions). /* DnD test for QWidgetWindow (handleDrag*Event() functions).

View File

@ -46,6 +46,8 @@
#include <qwindow.h> #include <qwindow.h>
#include <qwidget.h> #include <qwidget.h>
#include <qdockwidget.h>
#include <qmainwindow.h>
class Window : public QWindow class Window : public QWindow
@ -80,6 +82,7 @@ private slots:
void testUnparenting(); void testUnparenting();
void testActivation(); void testActivation();
void testAncestorChange(); void testAncestorChange();
void testDockWidget();
}; };
@ -278,6 +281,7 @@ void tst_QWindowContainer::testAncestorChange()
newRoot->setGeometry(100, 100, 200, 200); newRoot->setGeometry(100, 100, 200, 200);
newRoot->show(); newRoot->show();
QVERIFY(QTest::qWaitForWindowExposed(newRoot)); QVERIFY(QTest::qWaitForWindowExposed(newRoot));
QCOMPARE(newRoot->windowHandle(), window->parent());
// newRoot // newRoot
// + right // + right
// + container // + container
@ -285,6 +289,31 @@ void tst_QWindowContainer::testAncestorChange()
QCOMPARE(window->geometry(), QRect(100, 0, 100, 100)); QCOMPARE(window->geometry(), QRect(100, 0, 100, 100));
} }
void tst_QWindowContainer::testDockWidget()
{
QMainWindow mainWindow;
mainWindow.resize(200, 200);
QDockWidget *dock = new QDockWidget();
QWindow *window = new QWindow();
QWidget *container = QWidget::createWindowContainer(window);
dock->setWidget(container);
mainWindow.addDockWidget(Qt::RightDockWidgetArea, dock);
mainWindow.show();
QVERIFY(QTest::qWaitForWindowExposed(&mainWindow));
QVERIFY(window->parent() == mainWindow.window()->windowHandle());
QTest::qWait(1000);
dock->setFloating(true);
QTRY_VERIFY(window->parent() != mainWindow.window()->windowHandle());
QTest::qWait(1000);
dock->setFloating(false);
QTRY_VERIFY(window->parent() == mainWindow.window()->windowHandle());
}
QTEST_MAIN(tst_QWindowContainer) QTEST_MAIN(tst_QWindowContainer)
#include "tst_qwindowcontainer.moc" #include "tst_qwindowcontainer.moc"

View File

@ -384,7 +384,7 @@ void Configure::parseCmdLine()
configCmdLine.clear(); configCmdLine.clear();
reloadCmdLine(); reloadCmdLine();
} else { } else {
dictionary[ "HELP" ] = "yes"; dictionary[ "DONE" ] = "error";
} }
i = 0; i = 0;
} }
@ -1304,7 +1304,7 @@ void Configure::parseCmdLine()
} }
else { else {
dictionary[ "HELP" ] = "yes"; dictionary[ "DONE" ] = "error";
cout << "Unknown option " << configCmdLine.at(i) << endl; cout << "Unknown option " << configCmdLine.at(i) << endl;
break; break;
} }
@ -1324,7 +1324,7 @@ void Configure::parseCmdLine()
if (dictionary["QMAKESPEC"].toLower() == "features" if (dictionary["QMAKESPEC"].toLower() == "features"
|| !mkspecs.contains(dictionary["QMAKESPEC"], Qt::CaseInsensitive)) { || !mkspecs.contains(dictionary["QMAKESPEC"], Qt::CaseInsensitive)) {
dictionary[ "HELP" ] = "yes"; dictionary[ "DONE" ] = "error";
if (dictionary ["QMAKESPEC_FROM"] == "commandline") { if (dictionary ["QMAKESPEC_FROM"] == "commandline") {
cout << "Invalid option \"" << dictionary["QMAKESPEC"] << "\" for -platform." << endl; cout << "Invalid option \"" << dictionary["QMAKESPEC"] << "\" for -platform." << endl;
} else if (dictionary ["QMAKESPEC_FROM"] == "env") { } else if (dictionary ["QMAKESPEC_FROM"] == "env") {
@ -1362,10 +1362,10 @@ void Configure::parseCmdLine()
const QStringList family = devices.filter(dictionary["XQMAKESPEC"], Qt::CaseInsensitive); const QStringList family = devices.filter(dictionary["XQMAKESPEC"], Qt::CaseInsensitive);
if (family.isEmpty()) { if (family.isEmpty()) {
dictionary["HELP"] = "yes"; dictionary[ "DONE" ] = "error";
cout << "Error: No device matching '" << dictionary["XQMAKESPEC"] << "'." << endl; cout << "Error: No device matching '" << dictionary["XQMAKESPEC"] << "'." << endl;
} else if (family.size() > 1) { } else if (family.size() > 1) {
dictionary["HELP"] = "yes"; dictionary[ "DONE" ] = "error";
cout << "Error: Multiple matches for device '" << dictionary["XQMAKESPEC"] << "'. Candidates are:" << endl; cout << "Error: Multiple matches for device '" << dictionary["XQMAKESPEC"] << "'. Candidates are:" << endl;
@ -1380,7 +1380,7 @@ void Configure::parseCmdLine()
// Ensure that -spec (XQMAKESPEC) exists in the mkspecs folder as well // Ensure that -spec (XQMAKESPEC) exists in the mkspecs folder as well
if (dictionary.contains("XQMAKESPEC") && if (dictionary.contains("XQMAKESPEC") &&
!mkspecs.contains(dictionary["XQMAKESPEC"], Qt::CaseInsensitive)) { !mkspecs.contains(dictionary["XQMAKESPEC"], Qt::CaseInsensitive)) {
dictionary["HELP"] = "yes"; dictionary[ "DONE" ] = "error";
cout << "Invalid option \"" << dictionary["XQMAKESPEC"] << "\" for -xplatform." << endl; cout << "Invalid option \"" << dictionary["XQMAKESPEC"] << "\" for -xplatform." << endl;
} }
} }
@ -1432,7 +1432,8 @@ void Configure::parseCmdLine()
for (QStringList::Iterator it = disabledModules.begin(); it != disabledModules.end(); ++it) for (QStringList::Iterator it = disabledModules.begin(); it != disabledModules.end(); ++it)
qtConfig.removeAll(*it); qtConfig.removeAll(*it);
if ((dictionary[ "REDO" ] != "yes") && (dictionary[ "HELP" ] != "yes")) if ((dictionary[ "REDO" ] != "yes") && (dictionary[ "HELP" ] != "yes")
&& (dictionary[ "DONE" ] != "error"))
saveCmdLine(); saveCmdLine();
} }
@ -1461,7 +1462,7 @@ void Configure::validateArgs()
if (!QFileInfo::exists(cfgpath)) { if (!QFileInfo::exists(cfgpath)) {
cfgpath = QFileInfo(dictionary["QCONFIG"]).absoluteFilePath(); cfgpath = QFileInfo(dictionary["QCONFIG"]).absoluteFilePath();
if (!QFileInfo::exists(cfgpath)) { if (!QFileInfo::exists(cfgpath)) {
dictionary[ "HELP" ] = "yes"; dictionary[ "DONE" ] = "error";
cout << "No such configuration \"" << qPrintable(dictionary["QCONFIG"]) << "\"" << endl ; cout << "No such configuration \"" << qPrintable(dictionary["QCONFIG"]) << "\"" << endl ;
return; return;
} }
@ -2825,7 +2826,6 @@ void Configure::generateOutputVars()
cout << "Configure could not detect your compiler. QMAKESPEC must either" << endl cout << "Configure could not detect your compiler. QMAKESPEC must either" << endl
<< "be defined as an environment variable, or specified as an" << endl << "be defined as an environment variable, or specified as an" << endl
<< "argument with -platform" << endl; << "argument with -platform" << endl;
dictionary[ "HELP" ] = "yes";
QStringList winPlatforms; QStringList winPlatforms;
QDir mkspecsDir(sourcePath + "/mkspecs"); QDir mkspecsDir(sourcePath + "/mkspecs");