From 7ee4ab14636ee39670b5b25c3afa90009665eede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 1 Feb 2013 13:25:37 +0100 Subject: [PATCH 01/10] Cocoa: Improve expose event handling. Send expose events on window and view show/hide notifications. Implement QCocoaWindow::isExposed. Close all windows on quit. This allows sending (de-)expose events for those windows while the event loop is running. Remove the flushWindowSystemEvents call in setVisible. This function is called from application code. Flushing window system events here is wrong since it can lead to events being processed in the middle of the user code call stack. flushWindowSystemEvents should only be called as a result of (native) window system activity. Skip one of the tst_qtooltip tests which becomes unstable/ fails in the CI system as a result of this change. Task-number: QTBUG-29583 Change-Id: I3fb8b3f77e2b2e19dfeafba5d7dfcef602891d37 Reviewed-by: Gabriel de Dietrich Reviewed-by: Gunnar Sletta --- .../cocoa/qcocoaapplicationdelegate.mm | 8 +++++ src/plugins/platforms/cocoa/qcocoawindow.h | 4 +++ src/plugins/platforms/cocoa/qcocoawindow.mm | 33 ++++++++++++++++--- src/plugins/platforms/cocoa/qnsview.h | 2 ++ src/plugins/platforms/cocoa/qnsview.mm | 18 +++++++--- .../widgets/kernel/qtooltip/tst_qtooltip.cpp | 4 +++ 6 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 55f94df45a..e756c375f3 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -202,6 +202,14 @@ static void cleanupCocoaApplicationDelegate() if ([self canQuit]) { if (!startedQuit) { startedQuit = true; + // Close open windows. This is done in order to deliver de-expose + // events while the event loop is still running. + const QWindowList topLevels = QGuiApplication::topLevelWindows(); + for (int i = 0; i < topLevels.size(); ++i) { + QWindow *window = topLevels.at(i); + topLevels.at(i)->close(); + } + QGuiApplication::exit(0); startedQuit = false; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 324a43c8ae..7140a68d49 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -108,6 +108,7 @@ public: void setWindowIcon(const QIcon &icon); void raise(); void lower(); + bool isExposed() const; void propagateSizeHints(); void setOpacity(qreal level); void setMask(const QRegion ®ion); @@ -143,6 +144,8 @@ public: QCocoaMenuBar *menubar() const; qreal devicePixelRatio() const; + void exposeWindow(); + void obscureWindow(); protected: // NSWindow handling. The QCocoaWindow/QNSView can either be displayed // in an existing NSWindow or in one created by Qt. @@ -174,6 +177,7 @@ public: // for QNSView bool m_hasModalSession; bool m_frameStrutEventsEnabled; + bool m_isExposed; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 45100f9906..7c665a35c5 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -194,6 +194,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_menubar(0) , m_hasModalSession(false) , m_frameStrutEventsEnabled(false) + , m_isExposed(false) { #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug() << "QCocoaWindow::QCocoaWindow" << this; @@ -273,9 +274,12 @@ void QCocoaWindow::setVisible(bool visible) } - // Make sure the QWindow has a frame ready before we show the NSWindow. - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); - QWindowSystemInterface::flushWindowSystemEvents(); + // This call is here to handle initial window show correctly: + // - top-level windows need to have backing store content ready when the + // window is shown, sendin the expose event here makes that more likely. + // - QNSViews for child windows are initialy not hidden and won't get the + // viewDidUnhide message. + exposeWindow(); if (m_nsWindow) { // setWindowState might have been called while the window was hidden and @@ -327,8 +331,6 @@ void QCocoaWindow::setVisible(bool visible) } else { [m_contentView setHidden:YES]; } - if (!QCoreApplication::closingDown()) - QWindowSystemInterface::handleExposeEvent(window(), QRegion()); } } @@ -478,6 +480,11 @@ void QCocoaWindow::lower() [m_nsWindow orderBack: m_nsWindow]; } +bool QCocoaWindow::isExposed() const +{ + return m_isExposed; +} + void QCocoaWindow::propagateSizeHints() { QCocoaAutoReleasePool pool; @@ -847,6 +854,22 @@ qreal QCocoaWindow::devicePixelRatio() const } } +void QCocoaWindow::exposeWindow() +{ + if (!m_isExposed) { + m_isExposed = true; + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); + } +} + +void QCocoaWindow::obscureWindow() +{ + if (m_isExposed) { + m_isExposed = false; + QWindowSystemInterface::handleExposeEvent(window(), QRegion()); + } +} + QMargins QCocoaWindow::frameMargins() const { NSRect frameW = [m_nsWindow frame]; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index b4b3379a82..2175b24e98 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -79,6 +79,8 @@ QT_END_NAMESPACE - (void)drawRect:(NSRect)dirtyRect; - (void)updateGeometry; - (void)windowNotification : (NSNotification *) windowNotification; +- (void)viewDidHide; +- (void)viewDidUnhide; - (BOOL)isFlipped; - (BOOL)acceptsFirstResponder; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 1d59592e7d..a50cc34893 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -227,10 +227,10 @@ static QTouchDevice *touchDevice = 0; 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 if ([notificationName isEqualToString: @"NSWindowDidOrderOffScreenNotification"]) { + m_platformWindow->obscureWindow(); + } else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) { + m_platformWindow->exposeWindow(); } else { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 @@ -246,6 +246,16 @@ static QTouchDevice *touchDevice = 0; } } +- (void)viewDidHide +{ + m_platformWindow->obscureWindow(); +} + +- (void)viewDidUnhide +{ + m_platformWindow->exposeWindow(); +} + - (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset { m_backingStore = backingStore; diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp index f16fe49712..2d3e3c1702 100644 --- a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp +++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp @@ -103,6 +103,10 @@ void tst_QToolTip::task183679() QFETCH(Qt::Key, key); QFETCH(bool, visible); +#ifdef Q_OS_MAC + QSKIP("This test fails in the CI system, QTBUG-30040"); +#endif + Widget_task183679 widget; widget.show(); QApplication::setActiveWindow(&widget); From 711773776ed324efce7f1ed227104da9c7e21e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 25 Feb 2013 09:58:34 +0100 Subject: [PATCH 02/10] Fixed potential access violation in QPixmap::copy() for <32 bit pixmaps. QImage is supposed to maintain the invariant that each scan-line begins on a 4-byte boundary, so we need to verify that this is the case before using the optimized path of short-cutting QImage::copy() by referencing the source image's bits directly. Task-number: QTBUG-14766 Change-Id: I0a178aeb2f34cc64f98deae9470b55b5c53fcb06 Reviewed-by: Gunnar Sletta --- src/gui/image/qpixmap_raster.cpp | 5 +++-- tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index f0cb69f3ec..f8fef9cada 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -239,8 +239,9 @@ QImage QRasterPlatformPixmap::toImage(const QRect &rect) const return image; QRect clipped = rect.intersected(QRect(0, 0, w, h)); - if (d % 8 == 0) - return QImage(image.scanLine(clipped.y()) + clipped.x() * (d / 8), + const uint du = uint(d); + if ((du % 8 == 0) && (((uint(clipped.x()) * du)) % 32 == 0)) + return QImage(image.scanLine(clipped.y()) + clipped.x() * (du / 8), clipped.width(), clipped.height(), image.bytesPerLine(), image.format()); else diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index f5298a1690..61f53a5073 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -167,6 +167,8 @@ private slots: void scaled_QTBUG19157(); void detachOnLoad_QTBUG29639(); + + void copyOnNonAlignedBoundary(); }; static bool lenientCompare(const QPixmap &actual, const QPixmap &expected) @@ -1503,5 +1505,13 @@ void tst_QPixmap::detachOnLoad_QTBUG29639() QVERIFY(a.toImage() != b.toImage()); } +void tst_QPixmap::copyOnNonAlignedBoundary() +{ + QImage img(8, 2, QImage::Format_RGB16); + + QPixmap pm1 = QPixmap::fromImage(img, Qt::NoFormatConversion); + QPixmap pm2 = pm1.copy(QRect(5, 0, 3, 2)); // When copying second line: 2 bytes too many are read which might cause an access violation. +} + QTEST_MAIN(tst_QPixmap) #include "tst_qpixmap.moc" From b4d304742234d79548e06344e7bcdfa4081b1477 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 26 Feb 2013 11:25:52 +0100 Subject: [PATCH 03/10] require modules to define their version otherwise they would inherit it from qtbase, which may effectively result in a lie if building against a different release. for convenience we define the version centrally per repo. qtbase is special, in that we use the version defined in qglobal.h to avoid defining it redundantly (the instance in qglobal.h is currently needed to bootstrap qmake; the configures would need some work to change this). Task-number: QTBUG-29838 Change-Id: Ie9a5b0ff0d64b69ff2d34af2f7c42d6278e957cc Reviewed-by: Thiago Macieira --- .qmake.conf | 3 +++ mkspecs/features/qt_docs.prf | 8 +++++--- mkspecs/features/qt_module.prf | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.qmake.conf b/.qmake.conf index 5de255cb69..17dbc553bb 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,2 +1,5 @@ load(qt_build_config) CONFIG += qt_example_installs + +# In qtbase, all modules follow qglobal.h +MODULE_VERSION = $$QT_VERSION diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf index 31f7b65c38..c80efb03e0 100644 --- a/mkspecs/features/qt_docs.prf +++ b/mkspecs/features/qt_docs.prf @@ -25,11 +25,13 @@ QDOC += -outputdir $$QMAKE_DOCS_OUTPUTDIR !build_online_docs: \ QDOC += -installdir $$[QT_INSTALL_DOCS] qtver.name = QT_VERSION -qtver.value = $$QT_VERSION +qtver.value = $$VERSION +isEmpty(qtver.value): qtver.value = $$MODULE_VERSION +isEmpty(qtver.value): error("No version for documentation specified.") qtmver.name = QT_VER -qtmver.value = $${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION} +qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1) qtvertag.name = QT_VERSION_TAG -qtvertag.value = $$replace(QT_VERSION, \.,) +qtvertag.value = $$replace(qtver.value, \.,) qtAddToolEnv(QDOC, qtver qtmver qtvertag) doc_command = $$QDOC $$QMAKE_DOCS prepare_docs { diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 728d1f5f85..d015b213d7 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -20,7 +20,8 @@ load(qt_build_config) # loads qmodule.pri if hasn't been loaded already isEmpty(MODULE):MODULE = $$section($$list($$basename(_PRO_FILE_)), ., 0, 0) -isEmpty(VERSION):VERSION = $$QT_VERSION +isEmpty(VERSION): VERSION = $$MODULE_VERSION +isEmpty(VERSION): error("Module does not define version.") # Compile as shared/DLL or static according to the option given to configure # unless overridden. Host builds are always static From 5a8378556781d8bd84f7c43840efacf7f0a59663 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 1 Mar 2013 12:01:42 +0100 Subject: [PATCH 04/10] Correct sentence in QNetworkProxy::setApplicationProxy() documentation. Change-Id: I46fa7f814901cbe6a1f8f003f461bf1eee6f8bde Reviewed-by: Shane Kearns Reviewed-by: Jerome Pasion Reviewed-by: Jonas Gastal --- src/network/kernel/qnetworkproxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index 242855eaba..54229295bb 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -706,7 +706,7 @@ quint16 QNetworkProxy::port() const If a QAbstractSocket or QTcpSocket has the QNetworkProxy::DefaultProxy type, then the QNetworkProxy set with this function is used. If you want more flexibility in determining - which the proxy, use the QNetworkProxyFactory class. + which proxy is used, use the QNetworkProxyFactory class. Setting a default proxy value with this function will override the application proxy factory set with From 544f1cbe2752e1bcc69729e2aeeae49b8683afdb Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 26 Feb 2013 15:34:00 +0100 Subject: [PATCH 05/10] Cocoa: Fix shadowless popups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The window shadow was never invalidated after setting the transparency mask. We now do it right after the first draw after setting the mask. Change-Id: Icc5c6002d25abeb25d58ee4d1f868e928121ae9b Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.h | 2 ++ src/plugins/platforms/cocoa/qnsview.mm | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 2175b24e98..853b4b99e1 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -59,6 +59,7 @@ QT_END_NAMESPACE QPoint m_backingStoreOffset; CGImageRef m_maskImage; uchar *m_maskData; + bool m_shouldInvalidateWindowShadow; QWindow *m_window; QCocoaWindow *m_platformWindow; Qt::MouseButtons m_buttons; @@ -76,6 +77,7 @@ QT_END_NAMESPACE - (void)setQCocoaGLContext:(QCocoaGLContext *)context; - (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset; - (void)setMaskRegion:(const QRegion *)region; +- (void)invalidateWindowShadowIfNeeded; - (void)drawRect:(NSRect)dirtyRect; - (void)updateGeometry; - (void)windowNotification : (NSNotification *) windowNotification; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a50cc34893..b769ebf120 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -80,6 +80,7 @@ static QTouchDevice *touchDevice = 0; m_backingStore = 0; m_maskImage = 0; m_maskData = 0; + m_shouldInvalidateWindowShadow = false; m_window = 0; m_buttons = Qt::NoButton; m_sendKeyEvent = false; @@ -266,6 +267,7 @@ static QTouchDevice *touchDevice = 0; - (void) setMaskRegion:(const QRegion *)region { + m_shouldInvalidateWindowShadow = true; if (m_maskImage) CGImageRelease(m_maskImage); if (region->isEmpty()) { @@ -285,6 +287,14 @@ static QTouchDevice *touchDevice = 0; m_maskImage = qt_mac_toCGImage(maskImage, true, &m_maskData); } +- (void)invalidateWindowShadowIfNeeded +{ + if (m_shouldInvalidateWindowShadow && m_platformWindow->m_nsWindow) { + [m_platformWindow->m_nsWindow invalidateShadow]; + m_shouldInvalidateWindowShadow = false; + } +} + - (void) drawRect:(NSRect)dirtyRect { if (!m_backingStore) @@ -334,6 +344,8 @@ static QTouchDevice *touchDevice = 0; CGContextRestoreGState(cgContext); CGImageRelease(cleanImg); CGImageRelease(subMask); + + [self invalidateWindowShadowIfNeeded]; } - (BOOL) isFlipped From 083c8ce840216ab412bd8d20d5f61a7e24a6d615 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 26 Feb 2013 17:26:57 +0100 Subject: [PATCH 06/10] Cocoa: Pick right rectangle when rendering window mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ususally, the object setting the mask knows better than the window, since the latter may not have had its size set by then. Task-number: QTBUG-29856 Change-Id: Ib24d452a98a76b57f5d9236d5fa1ba4755cf0840 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index b769ebf120..fae68493f1 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -274,7 +274,7 @@ static QTouchDevice *touchDevice = 0; m_maskImage = 0; } - const QRect &rect = qt_mac_toQRect([self frame]); + const QRect &rect = region->boundingRect(); QImage maskImage(rect.size(), QImage::Format_RGB888); maskImage.fill(Qt::white); QPainter p(&maskImage); From 3f5633bc254cdaea7edf1cf1951a7c4c1ba2a487 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 25 Feb 2013 19:54:48 +0100 Subject: [PATCH 07/10] remove some cryptic code relating to output directories the purpose of it is truly elusive - the output directory is maintained by the surrounding code anyway. Change-Id: Id1a481d85a7b83ab0676ef650c900414d0ba83b3 Reviewed-by: Joerg Bornemann --- qmake/generators/metamakefile.cpp | 16 ++++++---------- qmake/generators/metamakefile.h | 2 +- qmake/main.cpp | 2 +- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index 8c10d7d306..e3fa39c7e4 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -79,7 +79,7 @@ public: virtual bool init(); virtual int type() const { return BUILDSMETATYPE; } - virtual bool write(const QString &); + virtual bool write(); }; void @@ -149,7 +149,7 @@ BuildsMetaMakefileGenerator::init() } bool -BuildsMetaMakefileGenerator::write(const QString &oldpwd) +BuildsMetaMakefileGenerator::write() { Build *glue = 0; if(!makefiles.isEmpty() && !makefiles.first()->build.isNull()) { @@ -181,7 +181,6 @@ BuildsMetaMakefileGenerator::write(const QString &oldpwd) if(Option::output.fileName().isEmpty() && Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE) Option::output.setFileName(project->first("QMAKE_MAKEFILE").toQString()); - Option::output_dir = oldpwd; QString build_name = build->name; if(!build->build.isEmpty()) { if(!build_name.isEmpty()) @@ -268,7 +267,7 @@ public: virtual bool init(); virtual int type() const { return SUBDIRSMETATYPE; } - virtual bool write(const QString &); + virtual bool write(); }; bool @@ -349,7 +348,7 @@ SubdirsMetaMakefileGenerator::init() } else { const QString output_name = Option::output.fileName(); Option::output.setFileName(sub->output_file); - hasError |= !sub->makefile->write(sub->output_dir); + hasError |= !sub->makefile->write(); delete sub; qmakeClearCaches(); sub = 0; @@ -378,7 +377,7 @@ SubdirsMetaMakefileGenerator::init() } bool -SubdirsMetaMakefileGenerator::write(const QString &oldpwd) +SubdirsMetaMakefileGenerator::write() { bool ret = true; const QString &pwd = qmake_getpwd(); @@ -397,10 +396,7 @@ SubdirsMetaMakefileGenerator::write(const QString &oldpwd) printf("Writing %s\n", QDir::cleanPath(Option::output_dir+"/"+ Option::output.fileName()).toLatin1().constData()); } - QString writepwd = Option::fixPathToLocalOS(qmake_getpwd()); - if(!writepwd.startsWith(Option::fixPathToLocalOS(oldpwd))) - writepwd = oldpwd; - if(!(ret = subs.at(i)->makefile->write(writepwd))) + if (!(ret = subs.at(i)->makefile->write())) break; //restore because I'm paranoid qmake_setpwd(pwd); diff --git a/qmake/generators/metamakefile.h b/qmake/generators/metamakefile.h index 85106a674d..aff2f422a6 100644 --- a/qmake/generators/metamakefile.h +++ b/qmake/generators/metamakefile.h @@ -69,7 +69,7 @@ public: virtual bool init() = 0; virtual int type() const { return -1; } - virtual bool write(const QString &oldpwd) = 0; + virtual bool write() = 0; }; QT_END_NAMESPACE diff --git a/qmake/main.cpp b/qmake/main.cpp index 5f9fb05449..e339239289 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -187,7 +187,7 @@ int runQMake(int argc, char **argv) if (!success) exit_val = 3; - if(mkfile && !mkfile->write(oldpwd)) { + if (mkfile && !mkfile->write()) { if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) fprintf(stderr, "Unable to generate project file.\n"); else From a8c6708260544b8d801cf823c601f39c4f06bf74 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 4 Mar 2013 10:47:01 +0100 Subject: [PATCH 08/10] Correct QLocale(const QString &) documentation. Change-Id: I6430ff2636083204fa12437980626260f848e269 Reviewed-by: Jerome Pasion --- src/corelib/tools/qlocale.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 39257158a4..365033d84a 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -736,13 +736,13 @@ QLocale::QLocale(QLocalePrivate &dd) The separator can be either underscore or a minus sign. If the string violates the locale format, or language is not - a valid ISO 369 code, the "C" locale is used instead. If country + a valid ISO 639 code, the "C" locale is used instead. If country is not present, or is not a valid ISO 3166 code, the most appropriate country is chosen for the specified language. The language, script and country codes are converted to their respective \c Language, \c Script and \c Country enums. After this conversion is - performed the constructor behaves exactly like QLocale(Country, Script, + performed, the constructor behaves exactly like QLocale(Country, Script, Language). This constructor is much slower than QLocale(Country, Script, Language). From 7128bcbbd5b0597bfb36e6f0b3d148d5dfb1c3bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 5 Mar 2013 16:08:40 +0100 Subject: [PATCH 09/10] Attempt to stabilize tst_qgl::graphicsViewClipping(). Make sure the graphics view is exposed and has been painted before trying to grab the framebuffer. Task-number: QTBUG-29943 Change-Id: I2945cb78b58265864744a0d5fc99fb430306b578 Reviewed-by: Gunnar Sletta --- tests/auto/opengl/qgl/tst_qgl.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp index 6c5c90d737..d4d109b981 100644 --- a/tests/auto/opengl/qgl/tst_qgl.cpp +++ b/tests/auto/opengl/qgl/tst_qgl.cpp @@ -832,10 +832,19 @@ static void fuzzyCompareImages(const QImage &testImage, const QImage &referenceI class UnclippedWidget : public QWidget { public: + bool painted; + + UnclippedWidget() + : painted(false) + { + } + void paintEvent(QPaintEvent *) { QPainter p(this); p.fillRect(rect().adjusted(-1000, -1000, 1000, 1000), Qt::black); + + painted = true; } }; @@ -865,7 +874,9 @@ void tst_QGL::graphicsViewClipping() scene.setSceneRect(view.viewport()->rect()); - QVERIFY(QTest::qWaitForWindowActive(&view)); + QTest::qWaitForWindowExposed(&view); + + QTRY_VERIFY(widget->painted); QImage image = viewport->grabFrameBuffer(); QImage expected = image; From a12f6ba302e54c1570c54aa4c722f2dafbf794af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 5 Mar 2013 15:43:50 +0100 Subject: [PATCH 10/10] Fixed dashes being rendered differently depending on system clip. We need to clip lines to the unclipped device rect in the case of dashing, since otherwise the dashes will be shifted and rendered differently when partial repaints are done. Task-number: QTBUG-24762 Change-Id: I3599b54baa552acc20bf8cc2e12f846b45f6019e Reviewed-by: Lars Knoll Reviewed-by: Gunnar Sletta --- src/gui/painting/qcosmeticstroker.cpp | 11 ++++-- src/gui/painting/qcosmeticstroker_p.h | 4 +- src/gui/painting/qpaintengine_raster.cpp | 26 ++++++------- src/gui/painting/qpaintengine_raster_p.h | 1 + .../gui/painting/qpainter/tst_qpainter.cpp | 38 +++++++++++++++++++ 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index 1ba55aa7f1..1de955bc13 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -290,11 +290,14 @@ void QCosmeticStroker::setup() ppl = buffer->bytesPerLine()>>2; } + // dashes are sensitive to clips, so we need to clip consistently when painting to the same device + QRect clipRect = strokeSelection & Dashed ? deviceRect : clip; + // setup FP clip bounds - xmin = clip.left() - 1; - xmax = clip.right() + 2; - ymin = clip.top() - 1; - ymax = clip.bottom() + 2; + xmin = clipRect.left() - 1; + xmax = clipRect.right() + 2; + ymin = clipRect.top() - 1; + ymax = clipRect.bottom() + 2; lastPixel.x = -1; } diff --git a/src/gui/painting/qcosmeticstroker_p.h b/src/gui/painting/qcosmeticstroker_p.h index 136b014424..f4fb5fab30 100644 --- a/src/gui/painting/qcosmeticstroker_p.h +++ b/src/gui/painting/qcosmeticstroker_p.h @@ -85,8 +85,9 @@ public: HorizontalMask = 0xc }; - QCosmeticStroker(QRasterPaintEngineState *s, const QRect &dr) + QCosmeticStroker(QRasterPaintEngineState *s, const QRect &dr, const QRect &dr_unclipped) : state(s), + deviceRect(dr_unclipped), clip(dr), pattern(0), reversePattern(0), @@ -110,6 +111,7 @@ public: QRasterPaintEngineState *state; + QRect deviceRect; QRect clip; // clip bounds in real qreal xmin, xmax; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index aaa0a4b87e..941e3ea71a 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1054,20 +1054,20 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, void QRasterPaintEnginePrivate::systemStateChanged() { - QRect clipRect(0, 0, + deviceRectUnclipped = QRect(0, 0, qMin(QT_RASTER_COORD_LIMIT, device->width()), qMin(QT_RASTER_COORD_LIMIT, device->height())); if (!systemClip.isEmpty()) { - QRegion clippedDeviceRgn = systemClip & clipRect; + QRegion clippedDeviceRgn = systemClip & deviceRectUnclipped; deviceRect = clippedDeviceRgn.boundingRect(); baseClip->setClipRegion(clippedDeviceRgn); } else { - deviceRect = clipRect; + deviceRect = deviceRectUnclipped; baseClip->setClipRect(deviceRect); } #ifdef QT_DEBUG_DRAW - qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip; + qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << deviceRectUnclipped << systemClip; #endif exDeviceRect = deviceRect; @@ -1529,7 +1529,7 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount) if (s->penData.blend) { QRectVectorPath path; if (s->flags.fast_pen) { - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); for (int i = 0; i < rectCount; ++i) { path.set(rects[i]); @@ -1576,7 +1576,7 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount) if (s->penData.blend) { QRectVectorPath path; if (s->flags.fast_pen) { - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); for (int i = 0; i < rectCount; ++i) { path.set(rects[i]); @@ -1610,7 +1610,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) return; if (s->flags.fast_pen) { - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPath(path); } else if (s->flags.non_complex_pen && path.shape() == QVectorPath::LinesHint) { @@ -1953,7 +1953,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly if (s->penData.blend) { QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode)); if (s->flags.fast_pen) { - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPath(vp); } else { @@ -2018,7 +2018,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg QVectorPath vp((qreal *) fpoints.data(), pointCount, 0, QVectorPath::polygonFlags(mode)); if (s->flags.fast_pen) { - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPath(vp); } else { @@ -3112,7 +3112,7 @@ void QRasterPaintEngine::drawPoints(const QPointF *points, int pointCount) return; } - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPoints(points, pointCount); } @@ -3132,7 +3132,7 @@ void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount) return; } - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPoints(points, pointCount); } @@ -3153,7 +3153,7 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) return; if (s->flags.fast_pen) { - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); for (int i=0; ipenData.blend) return; if (s->flags.fast_pen) { - QCosmeticStroker stroker(s, d->deviceRect); + QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped); stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); for (int i=0; i dashStroker; diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index cf520c06a9..774ade5fb0 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -280,6 +280,7 @@ private slots: void drawTextWithComplexBrush(); void QTBUG26013_squareCapStroke(); void QTBUG25153_drawLine(); + void dashing_systemClip(); private: void fillData(); @@ -4461,6 +4462,43 @@ void tst_QPainter::QTBUG25153_drawLine() } } +static void dashing_systemClip_paint(QPainter *p) +{ + p->setPen(QPen(Qt::black, 1, Qt::DashLine, Qt::RoundCap, Qt::MiterJoin)); + p->drawLine(8, 8, 42, 8); + p->drawLine(42, 8, 42, 42); + p->drawLine(42, 42, 8, 42); + p->drawLine(8, 42, 8, 8); +} + +void tst_QPainter::dashing_systemClip() +{ + QImage image(50, 50, QImage::Format_RGB32); + image.fill(Qt::white); + + QPainter p(&image); + dashing_systemClip_paint(&p); + p.end(); + + QImage old = image.copy(); + + image.paintEngine()->setSystemClip(QRect(10, 0, image.width() - 10, image.height())); + + p.begin(&image); + dashing_systemClip_paint(&p); + + // doing same paint operation again with different system clip should not change the image + QCOMPARE(old, image); + + old = image; + + p.setClipRect(QRect(20, 20, 30, 30)); + dashing_systemClip_paint(&p); + + // ditto for regular clips + QCOMPARE(old, image); +} + QTEST_MAIN(tst_QPainter) #include "tst_qpainter.moc"