From 88c4388022de192d2834ffa16b4d5f572993da58 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 25 Apr 2016 17:02:54 +0200 Subject: [PATCH 01/46] tst_QWidget: make it stable on OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch QSKIPs all tests that: - take to much time sitting in some QTRY_VERIFY or similar before failing - result in 'not in fullscreen mode' warning (with PASS) - thus completely flaky. - Where previously determined to not apply to OS X using QT_OS_MAC The intent is to make the test run-time more reasonable, both when running the test locally and on the CI system. Reduce the BLACKLIST - to avoid a 'double elimination' the tests that are skipped now, should not be BLACKLISTed so that we fix them for good. Task-number: QTBUG-52974 Change-Id: I34dc2010d0debc6b5b99f2375a6da902b7a17b29 Reviewed-by: Morten Johan Sørvig --- tests/auto/widgets/kernel/qwidget/BLACKLIST | 14 ----- .../widgets/kernel/qwidget/tst_qwidget.cpp | 62 ++++++++++++++++--- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index 4563da8d48..773f4205af 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -1,10 +1,8 @@ # OSX QTBUG-25300 QTBUG-45502 [normalGeometry] ubuntu-14.04 -osx [saveRestoreGeometry] ubuntu-14.04 -osx [restoreVersion1Geometry] ubuntu-14.04 osx @@ -20,20 +18,12 @@ ubuntu-14.04 ubuntu-14.04 [largerThanScreen_QTBUG30142] ubuntu-14.04 -[windowState] -osx [showMaximized] osx [setGeometry] osx -[stackUnder] -osx [raise] osx -[widgetAt] -osx -[sheetOpacity] -osx [resizeEvent] osx [setWindowGeometry] @@ -50,10 +40,6 @@ osx osx [render_systemClip] osx -[update] -osx -[doubleRepaint] -osx [childAt_unifiedToolBar] osx [showMinimizedKeepsFocus] diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index c2b01ea087..20bdf00292 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -1877,6 +1877,10 @@ void tst_QWidget::activation() void tst_QWidget::windowState() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + if (m_platform == QStringLiteral("xcb")) QSKIP("X11: Many window managers do not support window state properly, which causes this test to fail."); if (m_platform == QStringLiteral("wayland")) @@ -2088,6 +2092,10 @@ void tst_QWidget::showMaximized() void tst_QWidget::showFullScreen() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + if (m_platform == QStringLiteral("wayland")) QSKIP("Wayland: This fails. Figure out why."); QWidget plain; @@ -2447,6 +2455,10 @@ void tst_QWidget::reparent() // Qt/Embedded does it differently. void tst_QWidget::icon() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + QPixmap p(20,20); p.fill(Qt::red); testWidget->setWindowIcon(p); @@ -2498,6 +2510,10 @@ void tst_QWidget::hideWhenFocusWidgetIsChild() void tst_QWidget::normalGeometry() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + if (m_platform == QStringLiteral("wayland")) QSKIP("Wayland: This fails. Figure out why."); QWidget parent; @@ -2848,8 +2864,6 @@ void tst_QWidget::raise() } } -// Cocoa has no Z-Order for views, we hack it, but it results in paint events. -#ifndef QT_OS_MAC void tst_QWidget::lower() { QScopedPointer parent(new QWidget); @@ -2911,12 +2925,13 @@ void tst_QWidget::lower() list2 << child4 << child1 << child2 << child3; QCOMPARE(parent->children(), list2); } -#endif -// Cocoa has no Z-Order for views, we hack it, but it results in paint events. -#ifndef QT_OS_MAC void tst_QWidget::stackUnder() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974: Cocoa has no Z-Order for views, we hack it, but it results in paint events."); +#endif + QScopedPointer parent(new QWidget); parent->setObjectName(QLatin1String("stackUnder")); parent->setWindowTitle(parent->objectName()); @@ -2997,7 +3012,6 @@ void tst_QWidget::stackUnder() child->reset(); } } -#endif void drawPolygon(QPaintDevice *dev, int w, int h) { @@ -3086,6 +3100,10 @@ void tst_QWidget::testContentsPropagation() void tst_QWidget::saveRestoreGeometry() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + if (m_platform == QStringLiteral("wayland")) QSKIP("Wayland: This fails. Figure out why."); const QPoint position = m_availableTopLeft + QPoint(100, 100); @@ -3311,6 +3329,10 @@ void tst_QWidget::restoreVersion1Geometry() void tst_QWidget::widgetAt() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + if (m_platform == QStringLiteral("wayland")) QSKIP("Wayland: This fails. Figure out why."); Q_CHECK_PAINTEVENTS @@ -3526,6 +3548,7 @@ void tst_QWidget::testDeletionInEventHandlers() #ifdef Q_OS_OSX void tst_QWidget::sheetOpacity() { + QSKIP("QTBUG-52974: this test will most probably be deleted - to be investigated."); QWidget tmpWindow; QWidget sheet(&tmpWindow, Qt::Sheet); tmpWindow.show(); @@ -4176,6 +4199,10 @@ void tst_QWidget::showHideEventWhileMinimize() void tst_QWidget::update() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + QTest::qWait(10); // Wait for the initStuff to do it's stuff. Q_CHECK_PAINTEVENTS @@ -5165,10 +5192,13 @@ void tst_QWidget::showAndMoveChild() VERIFY_COLOR(parent, QRegion(parent.rect()) - child.geometry(), Qt::red); } -// Cocoa only has rect granularity. -#ifndef QT_OS_MAC + void tst_QWidget::subtractOpaqueSiblings() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974: Cocoa only has rect granularity."); +#endif + QWidget w; w.setGeometry(50, 50, 300, 300); @@ -5201,7 +5231,6 @@ void tst_QWidget::subtractOpaqueSiblings() QRegion(medium->geometry().translated(large->pos())) - tall->geometry()); } -#endif void tst_QWidget::deleteStyle() { @@ -5243,6 +5272,10 @@ public slots: void tst_QWidget::multipleToplevelFocusCheck() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + if (m_platform == QStringLiteral("wayland")) QSKIP("Wayland: This fails. Figure out why."); TopLevelFocusCheck w1; @@ -7916,6 +7949,10 @@ void tst_QWidget::sendUpdateRequestImmediately() void tst_QWidget::doubleRepaint() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + #if defined(Q_OS_OSX) if (!macHasAccessToWindowsServer()) QSKIP("Not having window server access causes the wrong number of repaints to be issues"); @@ -9580,6 +9617,10 @@ void tst_QWidget::childAt_unifiedToolBar() void tst_QWidget::taskQTBUG_11373() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974"); +#endif + QScopedPointer myWindow(new QMainWindow); QWidget * center = new QWidget(); myWindow -> setCentralWidget(center); @@ -10442,6 +10483,9 @@ public: // when mousing over it. void tst_QWidget::taskQTBUG_27643_enterEvents() { +#ifdef Q_OS_OSX + QSKIP("QTBUG-52974: this test can crash!"); +#endif // Move the mouse cursor to a safe location so it won't interfere QCursor::setPos(m_safeCursorPos); From 11ad50074b57df7559d39a0620a1e1b35d0ac061 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Wed, 27 Apr 2016 08:40:16 +0200 Subject: [PATCH 02/46] tst_qudpsocket - remove insignificant BLACKLIST should make it, recent regression in QUdpSocket went unnoticed (first) because of 'insignificant'. We'd like to avoid such regressions in future (again, using BLACKLIST if needed and fixig the real problem then). NB: BLACKLIST in this patch was extended to deal with previously unnoticed failures on Windows and OS X. 'multicast' and related family of of functions on OS X will probably stay like this (seems to be a Darwin's quirk), datagram size related tests - fixed in dev or 5.7 (change is in nativesocket engine, 'bytesAvailable'). Task-number: QTBUG-52714 Change-Id: I039b05935a02983ce1648de449907dfa765f7db7 Reviewed-by: Friedemann Kleint --- tests/auto/network/socket/qudpsocket/BLACKLIST | 12 ++++++++++++ tests/auto/network/socket/qudpsocket/test/test.pro | 2 -- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/auto/network/socket/qudpsocket/BLACKLIST b/tests/auto/network/socket/qudpsocket/BLACKLIST index 3e936aebf6..fb8455e6d3 100644 --- a/tests/auto/network/socket/qudpsocket/BLACKLIST +++ b/tests/auto/network/socket/qudpsocket/BLACKLIST @@ -6,3 +6,15 @@ osx osx [multicast:same bind, group ipv4 address] osx +[writeDatagramToNonExistingPeer] +windows +[asyncReadDatagram] +windows +[multicastLeaveAfterClose] +osx +[readyRead] +osx +[readyReadForEmptyDatagram] +osx +[asyncReadDatagram] +osx diff --git a/tests/auto/network/socket/qudpsocket/test/test.pro b/tests/auto/network/socket/qudpsocket/test/test.pro index 8ad16c652d..e4812416dc 100644 --- a/tests/auto/network/socket/qudpsocket/test/test.pro +++ b/tests/auto/network/socket/qudpsocket/test/test.pro @@ -22,5 +22,3 @@ wince* { } TARGET = tst_qudpsocket - -CONFIG+=insignificant_test # QTBUG-25367, QTBUG-25368 From 18048cae413c8eefefc40d73dd4a7b9005e7d137 Mon Sep 17 00:00:00 2001 From: Vladislav Tronko Date: Fri, 6 May 2016 15:14:31 +0300 Subject: [PATCH 03/46] Fix typo in QSqlTableModel documentation Change-Id: I4e9ab7469b028464186d3067759a2cf6fb187b07 Reviewed-by: Mark Brand --- src/sql/models/qsqltablemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 740c1b9b5d..6aa2eeb072 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -494,7 +494,7 @@ QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, in \since 5.0 Returns \c true if the model contains modified values that have not been - committed to the datase, otherwise false. + committed to the database, otherwise false. */ bool QSqlTableModel::isDirty() const { From 939b7bfe66221975d3a12a6d0a6dd14d9ad04344 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 2 May 2016 16:49:44 -0700 Subject: [PATCH 04/46] QCocoaMenuBar: set the native item's title Or, "Give Cocoa a Chance to do its Magic" Some menubar items, like the "Edit" menu, get extra items added at some point by Cocoa. Evidence points out to those extra items being added right after the NSMenu holding the menubar is set as the current menubar. At that point, both the child NSMenu and its NSMenuItem (the entry in the menubar) must have their title set. Therefore, we must set the menubar native item's title before QCocoaMenuBar::updateMenuBarImmediately() sets the main menu. Task-number: QTBUG-53085 Change-Id: Idd775cf0e3485739f38363a84cfed8d2db9cb662 Reviewed-by: Jake Petroules Reviewed-by: Liang Qi Reviewed-by: Marko Kangas Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoamenubar.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index ac48a0e310..a534d2064e 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -173,7 +173,9 @@ void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) } } - nativeItemForMenu(cocoaMenu).hidden = shouldHide; + NSMenuItem *nativeMenuItem = nativeItemForMenu(cocoaMenu); + nativeMenuItem.title = cocoaMenu->nsMenu().title; + nativeMenuItem.hidden = shouldHide; } NSMenuItem *QCocoaMenuBar::nativeItemForMenu(QCocoaMenu *menu) const From e6c0373421a3239a828969d5c49e5418b1122dd0 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 27 Apr 2016 13:18:41 -0700 Subject: [PATCH 05/46] Cocoa: Clear the backing store pointer when changing window If the geometry is being changed at some point while showing the widget after reparenting, we set the Cocoa frame on the QNSView. This results in Cocoa invalidating the view and calling drawRect: before we get a chance to flush the backing store. This may be an issue if the previous parent toplevel window has been deleted. In that case, the backing store pointer is a dangling one, resulting in a crash. Change-Id: I18b5dd7794a3bde8815daf3f84e4113a37aaea90 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qnsview.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 4b7b50a265..34c37d8aed 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -284,6 +284,7 @@ static bool _q_dontOverrideCtrlLMB = false; - (void)viewDidMoveToWindow { + m_backingStore = Q_NULLPTR; m_isMenuView = [self.window.className isEqualToString:@"NSCarbonMenuWindow"]; if (self.window) { // This is the case of QWidgetAction's generated QWidget inserted in an NSMenu. From 6eb27afcdfb6df2e620f1ec66196600f0f9ed022 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 19 Apr 2016 13:45:12 -0700 Subject: [PATCH 06/46] Cocoa: Add QCocoaWindowPointer This patch extends 5b54c352edbc597ec5283bc9cfdd77906350161f by abstracting the watcher pattern. The class is specialized for QCocoaWindow since it's aware of the QObject sentinel there. We update the usage in QNSWindowHelper and extend it to the forward window (this one is used for mouse coordinate conversion when docking windows). Change-Id: I628415527593daec835bbad1b6e83d13fe7b6703 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.h | 39 +++++++++++++++++---- src/plugins/platforms/cocoa/qcocoawindow.mm | 31 ++++++++++------ src/plugins/platforms/cocoa/qnsview.mm | 2 +- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index e60ca196ac..9fcb221d37 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -38,6 +38,7 @@ #include #include +#include #ifndef QT_NO_OPENGL #include "qcocoaglcontext.h" @@ -47,6 +48,32 @@ QT_FORWARD_DECLARE_CLASS(QCocoaWindow) +QT_BEGIN_NAMESPACE + +class QCocoaWindowPointer +{ +public: + void assign(QCocoaWindow *w); + void clear(); + + QCocoaWindow *data() const + { return watcher.isNull() ? Q_NULLPTR : window; } + bool isNull() const + { return watcher.isNull(); } + operator QCocoaWindow*() const + { return data(); } + QCocoaWindow *operator->() const + { return data(); } + QCocoaWindow &operator*() const + { return *data(); } + +private: + QPointer watcher; + QCocoaWindow *window; +}; + +QT_END_NAMESPACE + @class QT_MANGLE_NAMESPACE(QNSWindowHelper); @protocol QNSWindowProtocol @@ -63,14 +90,13 @@ typedef NSWindow QCocoaNSWindow; @interface QT_MANGLE_NAMESPACE(QNSWindowHelper) : NSObject { QCocoaNSWindow *_window; - QCocoaWindow *_platformWindow; + QCocoaWindowPointer _platformWindow; BOOL _grabbingMouse; BOOL _releaseOnMouseUp; - QPointer _watcher; } @property (nonatomic, readonly) QCocoaNSWindow *window; -@property (nonatomic, readonly) QCocoaWindow *platformWindow; +@property (nonatomic, readonly) QCocoaWindowPointer platformWindow; @property (nonatomic) BOOL grabbingMouse; @property (nonatomic) BOOL releaseOnMouseUp; @@ -254,7 +280,7 @@ public: // for QNSView NSView *m_contentView; QNSView *m_qtView; QCocoaNSWindow *m_nsWindow; - QCocoaWindow *m_forwardWindow; + QCocoaWindowPointer m_forwardWindow; // TODO merge to one variable if possible bool m_contentViewIsEmbedded; // true if the m_contentView is actually embedded in a "foreign" NSView hiearchy @@ -317,9 +343,8 @@ public: // for QNSView QHash m_contentBorderAreas; // identifer -> uppper/lower QHash m_enabledContentBorderAreas; // identifer -> enabled state (true/false) - // This object is tracked by a 'watcher' - // object in a window helper, preventing use of dangling - // pointers. + // This object is tracked by QCocoaWindowPointer, + // preventing the use of dangling pointers. QObject sentinel; }; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 12e85c5205..dd67946a27 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -85,7 +85,7 @@ static bool isMouseEvent(NSEvent *ev) self = [super init]; if (self) { _window = window; - _platformWindow = platformWindow; + _platformWindow.assign(platformWindow); _window.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:_platformWindow]; @@ -94,7 +94,6 @@ static bool isMouseEvent(NSEvent *ev) // make sure that m_nsWindow stays valid until the // QCocoaWindow is deleted by Qt. [_window setReleasedWhenClosed:NO]; - _watcher = &_platformWindow->sentinel; } return self; @@ -103,19 +102,19 @@ static bool isMouseEvent(NSEvent *ev) - (void)handleWindowEvent:(NSEvent *)theEvent { QCocoaWindow *pw = self.platformWindow; - if (_watcher && pw && pw->m_forwardWindow) { + if (pw && pw->m_forwardWindow) { if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) { QNSView *forwardView = pw->m_qtView; if (theEvent.type == NSLeftMouseUp) { [forwardView mouseUp:theEvent]; - pw->m_forwardWindow = 0; + pw->m_forwardWindow.clear(); } else { [forwardView mouseDragged:theEvent]; } } if (!pw->m_isNSWindowChild && theEvent.type == NSLeftMouseDown) { - pw->m_forwardWindow = 0; + pw->m_forwardWindow.clear(); } } @@ -142,7 +141,7 @@ static bool isMouseEvent(NSEvent *ev) if (!self.window.delegate) return; // Already detached, pending NSAppKitDefined event - if (_watcher && pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { + if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { NSPoint loc = [theEvent locationInWindow]; NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; NSRect contentFrame = [[self.window contentView] frame]; @@ -157,8 +156,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)detachFromPlatformWindow { - _platformWindow = 0; - _watcher.clear(); + self.platformWindow.clear(); [self.window.delegate release]; self.window.delegate = nil; } @@ -179,7 +177,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)dealloc { _window = nil; - _platformWindow = 0; + self.platformWindow.clear(); [super dealloc]; } @@ -331,6 +329,18 @@ static bool isMouseEvent(NSEvent *ev) @end +void QCocoaWindowPointer::assign(QCocoaWindow *w) +{ + window = w; + watcher = &w->sentinel; +} + +void QCocoaWindowPointer::clear() +{ + window = Q_NULLPTR; + watcher.clear(); +} + const int QCocoaWindow::NoAlertRequest = -1; QCocoaWindow::QCocoaWindow(QWindow *tlw) @@ -338,7 +348,6 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_contentView(nil) , m_qtView(nil) , m_nsWindow(0) - , m_forwardWindow(0) , m_contentViewIsEmbedded(false) , m_contentViewIsToBeEmbedded(false) , m_parentCocoaWindow(0) @@ -1320,7 +1329,7 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) if (oldParentCocoaWindow) { if (!m_isNSWindowChild || oldParentCocoaWindow != m_parentCocoaWindow) oldParentCocoaWindow->removeChildWindow(this); - m_forwardWindow = oldParentCocoaWindow; + m_forwardWindow.assign(oldParentCocoaWindow); } setNSWindow(m_nsWindow); diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 34c37d8aed..0d58faa5bf 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -741,7 +741,7 @@ QT_WARNING_POP if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp) targetView = m_platformWindow->m_forwardWindow->m_qtView; else - m_platformWindow->m_forwardWindow = 0; + m_platformWindow->m_forwardWindow.clear(); } // Popups implicitly grap mouse events; forward to the active popup if there is one From ee516381873857e833b53b175fd3c40e4c45a5fd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 6 May 2016 12:19:46 +0200 Subject: [PATCH 07/46] Windows Accessibility: Recurse up to find a window. Not all classes inheriting QAccessibleInterface implement QAccessibleInterface::window(), so, go up the hierarchy to find one that does. The window is required to be able to determine the correct scale factor for the screen when High DPI scaling is active. Fixes multimonitor issues for QtWidgets. Amends change d7a3b6145999d015997e26e12a7345f774b053f3. Task-number: QTBUG-52943 Change-Id: I81733765faee4d296bd6ea046bc2cecb018eb28d Reviewed-by: Frederik Gladhorn --- .../windows/accessible/qwindowsmsaaaccessible.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 5ca83fa9f2..71c197a32c 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -470,6 +470,15 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::Invoke(long dispIdMember, return hr; } +static const QWindow *windowOf(const QAccessibleInterface *ai) +{ + for ( ; ai; ai = ai->parent()) { + if (const QWindow *window = ai->window()) + return window; + } + return Q_NULLPTR; +} + /* IAccessible @@ -498,7 +507,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yT if (!accessible) return E_FAIL; - const QPoint pos = QHighDpi::fromNativeLocalPosition(QPoint(xLeft, yTop), accessible->window()); + const QPoint pos = QHighDpi::fromNativeLocalPosition(QPoint(xLeft, yTop), windowOf(accessible)); QAccessibleInterface *child = accessible->childAt(pos.x(), pos.y()); if (child == 0) { // no child found, return this item if it contains the coordinates @@ -541,7 +550,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long QAccessibleInterface *acc = childPointer(accessible, varID); if (!acc || !acc->isValid()) return E_FAIL; - const QRect rect = QHighDpi::toNativePixels(acc->rect(), accessible->window()); + const QRect rect = QHighDpi::toNativePixels(acc->rect(), windowOf(accessible)); *pxLeft = rect.x(); *pyTop = rect.y(); From 558c5c849cfd594c9e1cfb6edaffa0b524c852e9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 6 May 2016 11:20:49 +0200 Subject: [PATCH 08/46] QAccessibleWidget: Retrieve window from native parent widget. Query the native parent widget if the widget does not have a window handle. The window is required to be able to determine the correct scale factor for the screen when High DPI scaling is active. Change-Id: Ibaf5e8e7b07327ea635d2f726acea76c2c95bda3 Task-number: QTBUG-52943 Reviewed-by: Frederik Gladhorn --- src/widgets/accessible/qaccessiblewidget.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp index 3a9422cc26..beff27ad64 100644 --- a/src/widgets/accessible/qaccessiblewidget.cpp +++ b/src/widgets/accessible/qaccessiblewidget.cpp @@ -206,8 +206,14 @@ bool QAccessibleWidget::isValid() const /*! \reimp */ QWindow *QAccessibleWidget::window() const { - Q_ASSERT(widget()); - return widget()->windowHandle(); + const QWidget *w = widget(); + Q_ASSERT(w); + QWindow *result = w->windowHandle(); + if (!result) { + if (const QWidget *nativeParent = w->nativeParentWidget()) + result = nativeParent->windowHandle(); + } + return result; } /*! From 2c90973ebfd1ce61b4815bcef8a9ffc19f309f1a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 6 May 2016 11:23:25 +0200 Subject: [PATCH 09/46] QAccessibleMenuItem: Implement QAccessibleInterface::window(). The window is required to be able to determine the correct scale factor for the screen when High DPI scaling is active. Change-Id: I8f776684396d055754093f62e0d33bd7e23cb52b Task-number: QTBUG-52943 Reviewed-by: Frederik Gladhorn --- src/widgets/accessible/qaccessiblemenu.cpp | 14 ++++++++++++++ src/widgets/accessible/qaccessiblemenu_p.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp index a0a7852851..106f724464 100644 --- a/src/widgets/accessible/qaccessiblemenu.cpp +++ b/src/widgets/accessible/qaccessiblemenu.cpp @@ -225,6 +225,20 @@ QObject *QAccessibleMenuItem::object() const return m_action; } +/*! \reimp */ +QWindow *QAccessibleMenuItem::window() const +{ + QWindow *result = Q_NULLPTR; + if (!m_owner.isNull()) { + result = m_owner->windowHandle(); + if (!result) { + if (const QWidget *nativeParent = m_owner->nativeParentWidget()) + result = nativeParent->windowHandle(); + } + } + return result; +} + QRect QAccessibleMenuItem::rect() const { QRect rect; diff --git a/src/widgets/accessible/qaccessiblemenu_p.h b/src/widgets/accessible/qaccessiblemenu_p.h index b42c852ff1..c51597bf1f 100644 --- a/src/widgets/accessible/qaccessiblemenu_p.h +++ b/src/widgets/accessible/qaccessiblemenu_p.h @@ -108,6 +108,8 @@ public: QAccessibleInterface *parent() const Q_DECL_OVERRIDE; QAccessibleInterface *child(int index) const Q_DECL_OVERRIDE; QObject * object() const Q_DECL_OVERRIDE; + QWindow *window() const Q_DECL_OVERRIDE; + QRect rect() const Q_DECL_OVERRIDE; QAccessible::Role role() const Q_DECL_OVERRIDE; void setText(QAccessible::Text t, const QString & text) Q_DECL_OVERRIDE; From 1c2210b7b1ecae021d46c8e5a3cb4a53986067c4 Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Fri, 15 Jan 2016 15:45:27 +1000 Subject: [PATCH 10/46] make sure QNAM reacts to configuration changes Task-number: QTBUG-49760 Change-Id: Ic52fc9f7999f3dd00ef4022c959361782bd1ccd2 Reviewed-by: Markus Goetz (Woboq GmbH) --- src/network/access/qnetworkaccessmanager.cpp | 101 +++++++++++++++---- src/network/access/qnetworkaccessmanager.h | 2 + src/network/access/qnetworkaccessmanager_p.h | 5 + 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 28553e19e6..d023228fd2 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -474,6 +474,9 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) // connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), SLOT(_q_onlineStateChanged(bool))); + connect(&d->networkConfigurationManager, SIGNAL(configurationChanged(const QNetworkConfiguration &)), + SLOT(_q_configurationChanged(const QNetworkConfiguration &))); + #endif } @@ -1564,6 +1567,8 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); + QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(error(QNetworkSession::SessionError)), + q, SLOT(_q_networkSessionFailed(QNetworkSession::SessionError))); } //switch to new session (null if config was invalid) @@ -1571,7 +1576,6 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co networkSessionWeakRef = networkSessionStrongRef.toWeakRef(); if (!networkSessionStrongRef) { - online = false; if (networkAccessible == QNetworkAccessManager::NotAccessible || !online) emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible); @@ -1587,6 +1591,8 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co QObject::connect(networkSessionStrongRef.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection); QObject::connect(networkSessionStrongRef.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); + QObject::connect(networkSessionStrongRef.data(), SIGNAL(error(QNetworkSession::SessionError)), + q, SLOT(_q_networkSessionFailed(QNetworkSession::SessionError))); _q_networkSessionStateChanged(networkSessionStrongRef->state()); } @@ -1603,6 +1609,9 @@ void QNetworkAccessManagerPrivate::_q_networkSessionClosed() QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); + QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(error(QNetworkSession::SessionError)), + q, SLOT(_q_networkSessionFailed(QNetworkSession::SessionError))); + networkSessionStrongRef.clear(); networkSessionWeakRef.clear(); } @@ -1611,46 +1620,56 @@ void QNetworkAccessManagerPrivate::_q_networkSessionClosed() void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession::State state) { Q_Q(QNetworkAccessManager); - + bool reallyOnline = false; //Do not emit the networkSessionConnected signal here, except for roaming -> connected //transition, otherwise it is emitted twice in a row when opening a connection. - if (state == QNetworkSession::Connected && lastSessionState == QNetworkSession::Roaming) + if (state == QNetworkSession::Connected && lastSessionState != QNetworkSession::Roaming) emit q->networkSessionConnected(); lastSessionState = state; - if (online) { + if (online && state == QNetworkSession::Disconnected) { + Q_FOREACH (const QNetworkConfiguration &cfg, networkConfigurationManager.allConfigurations()) { + if (cfg.state().testFlag(QNetworkConfiguration::Active)) { + reallyOnline = true; + } + } + } else if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) { + reallyOnline = true; + } + + if (!reallyOnline) { if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { - online = false; if (networkAccessible != QNetworkAccessManager::NotAccessible) { networkAccessible = QNetworkAccessManager::NotAccessible; emit q->networkAccessibleChanged(networkAccessible); } } } else { - if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) { - online = true; - if (defaultAccessControl) - if (networkAccessible != QNetworkAccessManager::Accessible) { - networkAccessible = QNetworkAccessManager::Accessible; - emit q->networkAccessibleChanged(networkAccessible); - } - } + if (defaultAccessControl) + if (networkAccessible != QNetworkAccessManager::Accessible) { + networkAccessible = QNetworkAccessManager::Accessible; + emit q->networkAccessibleChanged(networkAccessible); + } + } + online = reallyOnline; + if (online && (state != QNetworkSession::Connected && state != QNetworkSession::Roaming)) { + _q_networkSessionClosed(); + createSession(q->configuration()); } } void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) { Q_Q(QNetworkAccessManager); + // if the user set a config, we only care whether this one is active. // Otherwise, this QNAM is online if there is an online config. if (customNetworkConfiguration) { online = (networkConfiguration.state() & QNetworkConfiguration::Active); } else { if (online != isOnline) { - if (isOnline) { - networkSessionStrongRef.clear(); - networkSessionWeakRef.clear(); - } + _q_networkSessionClosed(); + createSession(q->configuration()); online = isOnline; } } @@ -1661,11 +1680,6 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) emit q->networkAccessibleChanged(networkAccessible); } } - } else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) { - if (networkAccessible != QNetworkAccessManager::UnknownAccessibility) { - networkAccessible = QNetworkAccessManager::UnknownAccessibility; - emit q->networkAccessibleChanged(networkAccessible); - } } else { if (networkAccessible != QNetworkAccessManager::NotAccessible) { networkAccessible = QNetworkAccessManager::NotAccessible; @@ -1674,6 +1688,49 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) } } +void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfiguration &configuration) +{ + const QString id = configuration.identifier(); + if (configuration.state().testFlag(QNetworkConfiguration::Active)) { + if (!onlineConfigurations.contains(id)) { + + QSharedPointer session(getNetworkSession()); + if (session) { + if (online && session->configuration().identifier() + != networkConfigurationManager.defaultConfiguration().identifier()) { + + onlineConfigurations.insert(id); + //this one disconnected but another one is online, + // close and create new session + _q_networkSessionClosed(); + createSession(networkConfigurationManager.defaultConfiguration()); + } + } + } + + } else if (onlineConfigurations.contains(id)) { + //this one is disconnecting + onlineConfigurations.remove(id); + if (!onlineConfigurations.isEmpty()) { + _q_networkSessionClosed(); + createSession(configuration); + } + } +} + + +void QNetworkAccessManagerPrivate::_q_networkSessionFailed(QNetworkSession::SessionError) +{ + Q_FOREACH (const QNetworkConfiguration &cfg, networkConfigurationManager.allConfigurations()) { + if (cfg.state().testFlag(QNetworkConfiguration::Active)) { + online = true; + _q_networkSessionClosed(); + createSession(networkConfigurationManager.defaultConfiguration()); + return; + } + } +} + #endif // QT_NO_BEARERMANAGEMENT QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart) diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index c8df213ead..908d327e63 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -176,6 +176,8 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool)) + Q_PRIVATE_SLOT(d_func(), void _q_configurationChanged(const QNetworkConfiguration &)) + Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed(QNetworkSession::SessionError)) #endif }; diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 3fc33b5c15..2528249d17 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -143,6 +143,11 @@ public: bool isSeamless); void _q_networkSessionStateChanged(QNetworkSession::State state); void _q_onlineStateChanged(bool isOnline); + void _q_configurationChanged(const QNetworkConfiguration &configuration); + void _q_networkSessionFailed(QNetworkSession::SessionError error); + + QSet onlineConfigurations; + #endif QNetworkRequest prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart); From e1d0da65261077bfd720887d6e6216497abb4c5f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 13 Apr 2016 12:36:28 -0700 Subject: [PATCH 11/46] Fix Clang -Wexpansion-to-defined warning by deprecating QT_SUPPORTS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The C and C++ standards say it's undefined whether the preprocessor supports macros that expand to defined() will operate as an ifdef. Clang 3.9 started complaining about that fact. One solution was to change QT_SUPPORTS to check for zero or one, which means we need to change the #defines QT_NO_xxx to #define QT_NO_xxx 1. The C standard says we don't need to #define to 0, as an unknown token is interpreted as zero. However, that might produce a warning (GCC with -Wundef), so changing the macro this way is not recommended. Instead, we deprecate the macro and replace the uses with #ifdef/ndef. Change-Id: Id75834dab9ed466e94c7ffff1444874d5680b96a Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 3 ++ src/corelib/tools/qarraydata.cpp | 6 ++-- src/corelib/tools/qarraydata.h | 4 +-- src/corelib/tools/qarraydatapointer.h | 2 +- src/corelib/tools/qcontiguouscache.h | 2 +- src/corelib/tools/qhash.h | 2 +- src/corelib/tools/qlinkedlist.h | 2 +- src/corelib/tools/qlist.h | 2 +- src/corelib/tools/qmap.h | 2 +- src/corelib/tools/qrefcount.h | 6 ++-- src/corelib/tools/qset.h | 2 +- src/corelib/tools/qvector.h | 8 ++--- .../corelib/tools/qarraydata/simplevector.h | 2 +- .../tools/qarraydata/tst_qarraydata.cpp | 30 +++++++++---------- tests/auto/corelib/tools/qhash/tst_qhash.cpp | 2 +- .../tools/qlinkedlist/tst_qlinkedlist.cpp | 4 +-- tests/auto/corelib/tools/qlist/tst_qlist.cpp | 6 ++-- tests/auto/corelib/tools/qmap/tst_qmap.cpp | 4 +-- .../corelib/tools/qvector/tst_qvector.cpp | 22 +++++++------- 19 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 5bb1ce77bd..a7183cb983 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -55,6 +55,9 @@ #include #endif +// The QT_SUPPORTS macro is deprecated. Don't use it in new code. +// Instead, use #ifdef/ndef QT_NO_feature. +// ### Qt6: remove macro #ifdef _MSC_VER # define QT_SUPPORTS(FEATURE) (!defined QT_NO_##FEATURE) #else diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index fa6556f7d9..eb6ce21282 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -65,7 +65,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, // Don't allocate empty headers if (!(options & RawData) && !capacity) { -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) if (options & Unsharable) return const_cast(&qt_array_unsharable_empty); #endif @@ -110,7 +110,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1) & ~(alignment - 1); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) header->ref.atomic.store(bool(!(options & Unsharable))); #else header->ref.atomic.store(1); @@ -132,7 +132,7 @@ void QArrayData::deallocate(QArrayData *data, size_t objectSize, && !(alignment & (alignment - 1))); Q_UNUSED(objectSize) Q_UNUSED(alignment) -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) if (data == &qt_array_unsharable_empty) return; #endif diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index 865bd4325d..cbbfe1bea2 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -72,7 +72,7 @@ struct Q_CORE_EXPORT QArrayData enum AllocationOption { CapacityReserved = 0x1, -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) Unsharable = 0x2, #endif RawData = 0x4, @@ -249,7 +249,7 @@ struct QTypedArrayData return allocate(/* capacity */ 0); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) static QTypedArrayData *unsharableEmpty() { Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData)); diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index 9804d2c2d5..615d7c5f80 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -127,7 +127,7 @@ public: return (!d->isMutable() || d->ref.isShared()); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) void setSharable(bool sharable) { if (needsDetach()) { diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 41d198f9bc..d546e949c2 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -96,7 +96,7 @@ public: inline void detach() { if (d->ref.load() != 1) detach_helper(); } inline bool isDetached() const { return d->ref.load() == 1; } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } #endif diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index a18dd74706..a5bde40fb8 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -266,7 +266,7 @@ public: inline void detach() { if (d->ref.isShared()) detach_helper(); } inline bool isDetached() const { return !d->ref.isShared(); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QHashData::shared_null) d->sharable = sharable; } #endif bool isSharedWith(const QHash &other) const { return d == other.d; } diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 110529d843..710bf5a9f2 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -99,7 +99,7 @@ public: inline void detach() { if (d->ref.isShared()) detach_helper2(this->e); } inline bool isDetached() const { return !d->ref.isShared(); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QLinkedListData::shared_null) d->sharable = sharable; } #endif inline bool isSharedWith(const QLinkedList &other) const { return d == other.d; } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index e04a6be1ab..381875e96f 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -169,7 +169,7 @@ public: } inline bool isDetached() const { return !d->ref.isShared(); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) inline void setSharable(bool sharable) { if (sharable == d->ref.isSharable()) diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index ed49e70f4e..7b5a643a1e 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -359,7 +359,7 @@ public: inline void detach() { if (d->ref.isShared()) detach_helper(); } inline bool isDetached() const { return !d->ref.isShared(); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) inline void setSharable(bool sharable) { if (sharable == d->ref.isSharable()) diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h index a390989e76..bff6885d65 100644 --- a/src/corelib/tools/qrefcount.h +++ b/src/corelib/tools/qrefcount.h @@ -47,7 +47,7 @@ class RefCount public: inline bool ref() Q_DECL_NOTHROW { int count = atomic.load(); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) if (count == 0) // !isSharable return false; #endif @@ -58,7 +58,7 @@ public: inline bool deref() Q_DECL_NOTHROW { int count = atomic.load(); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) if (count == 0) // !isSharable return false; #endif @@ -67,7 +67,7 @@ public: return atomic.deref(); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) bool setSharable(bool sharable) Q_DECL_NOTHROW { Q_ASSERT(!isShared()); diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 3f4208e8b3..7e7eb5210c 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -79,7 +79,7 @@ public: inline void detach() { q_hash.detach(); } inline bool isDetached() const { return q_hash.isDetached(); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) inline void setSharable(bool sharable) { q_hash.setSharable(sharable); } #endif diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 691872cb36..3154220634 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -100,7 +100,7 @@ public: inline void detach(); inline bool isDetached() const { return !d->ref.isShared(); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) inline void setSharable(bool sharable) { if (sharable == d->ref.isSharable()) @@ -376,7 +376,7 @@ template void QVector::detach() { if (!isDetached()) { -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) if (!d->alloc) d = Data::unsharableEmpty(); else @@ -533,7 +533,7 @@ void QVector::reallocData(const int asize, const int aalloc, QArrayData::Allo x = Data::allocate(aalloc, options); Q_CHECK_PTR(x); // aalloc is bigger then 0 so it is not [un]sharedEmpty -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) Q_ASSERT(x->ref.isSharable() || options.testFlag(QArrayData::Unsharable)); #endif Q_ASSERT(!x->ref.isStatic()); @@ -601,7 +601,7 @@ void QVector::reallocData(const int asize, const int aalloc, QArrayData::Allo Q_ASSERT(d->data()); Q_ASSERT(uint(d->size) <= d->alloc); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) Q_ASSERT(d != Data::unsharableEmpty()); #endif Q_ASSERT(aalloc ? d != Data::sharedNull() : d == Data::sharedNull()); diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h index 091d871e82..9c7e1ae228 100644 --- a/tests/auto/corelib/tools/qarraydata/simplevector.h +++ b/tests/auto/corelib/tools/qarraydata/simplevector.h @@ -93,7 +93,7 @@ public: bool isStatic() const { return d->ref.isStatic(); } bool isShared() const { return d->ref.isShared(); } bool isSharedWith(const SimpleVector &other) const { return d == other.d; } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) bool isSharable() const { return d->ref.isSharable(); } void setSharable(bool sharable) { d.setSharable(sharable); } #endif diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index 31e44bc3ae..31ade26067 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -44,7 +44,7 @@ struct SharedNullVerifier { Q_ASSERT(QArrayData::shared_null[0].ref.isStatic()); Q_ASSERT(QArrayData::shared_null[0].ref.isShared()); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) Q_ASSERT(QArrayData::shared_null[0].ref.isSharable()); #endif } @@ -101,7 +101,7 @@ void tst_QArrayData::referenceCounting() QCOMPARE(array.ref.atomic.load(), 1); QVERIFY(!array.ref.isStatic()); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QVERIFY(array.ref.isSharable()); #endif @@ -123,7 +123,7 @@ void tst_QArrayData::referenceCounting() // Now would be a good time to free/release allocated data } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) { // Reference counting initialized to 0 (non-sharable) QArrayData array = { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, 0 }; @@ -151,7 +151,7 @@ void tst_QArrayData::referenceCounting() QCOMPARE(array.ref.atomic.load(), -1); QVERIFY(array.ref.isStatic()); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QVERIFY(array.ref.isSharable()); #endif @@ -178,7 +178,7 @@ void tst_QArrayData::sharedNullEmpty() QCOMPARE(null->ref.atomic.load(), -1); QCOMPARE(empty->ref.atomic.load(), -1); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QVERIFY(null->ref.isSharable()); QVERIFY(empty->ref.isSharable()); #endif @@ -309,7 +309,7 @@ void tst_QArrayData::simpleVector() QVERIFY(!v7.isShared()); QVERIFY(!v8.isShared()); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QVERIFY(v1.isSharable()); QVERIFY(v2.isSharable()); QVERIFY(v3.isSharable()); @@ -502,7 +502,7 @@ void tst_QArrayData::simpleVector() for (int i = 0; i < 120; ++i) QCOMPARE(v1[i], v8[i % 10]); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) { v7.setSharable(true); QVERIFY(v7.isSharable()); @@ -672,7 +672,7 @@ void tst_QArrayData::allocate_data() QArrayData *shared_empty = QArrayData::allocate(0, Q_ALIGNOF(QArrayData), 0); QVERIFY(shared_empty); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QArrayData *unsharable_empty = QArrayData::allocate(0, Q_ALIGNOF(QArrayData), 0, QArrayData::Unsharable); QVERIFY(unsharable_empty); #endif @@ -686,7 +686,7 @@ void tst_QArrayData::allocate_data() } options[] = { { "Default", QArrayData::Default, false, true, shared_empty }, { "Reserved", QArrayData::CapacityReserved, true, true, shared_empty }, -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) { "Reserved | Unsharable", QArrayData::CapacityReserved | QArrayData::Unsharable, true, false, unsharable_empty }, @@ -736,7 +736,7 @@ void tst_QArrayData::allocate() else QCOMPARE(data->alloc, uint(capacity)); QCOMPARE(data->capacityReserved, uint(isCapacityReserved)); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QFETCH(bool, isSharable); QCOMPARE(data->ref.isSharable(), isSharable); #endif @@ -1316,7 +1316,7 @@ static inline bool arrayIsFilledWith(const QArrayDataPointer &array, void tst_QArrayData::setSharable_data() { -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QTest::addColumn >("array"); QTest::addColumn("size"); QTest::addColumn("capacity"); @@ -1362,7 +1362,7 @@ void tst_QArrayData::setSharable_data() void tst_QArrayData::setSharable() { -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QFETCH(QArrayDataPointer, array); QFETCH(size_t, size); QFETCH(size_t, capacity); @@ -1492,7 +1492,7 @@ void fromRawData_impl() QVERIFY((const T *)raw.constBegin() != array); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) { // Immutable, unsharable SimpleVector raw = SimpleVector::fromRawData(array, @@ -1578,7 +1578,7 @@ void tst_QArrayData::literals() QVERIFY(v.isStatic()); #endif -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QVERIFY(v.isSharable()); #endif QCOMPARE((void*)(const char*)(v.constBegin() + v.size()), (void*)(const char*)v.constEnd()); @@ -1629,7 +1629,7 @@ void tst_QArrayData::variadicLiterals() QVERIFY(v.isStatic()); -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QVERIFY(v.isSharable()); #endif QCOMPARE((const int *)(v.constBegin() + v.size()), (const int *)v.constEnd()); diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp index 6a5c6b5670..d485040a14 100644 --- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp +++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp @@ -1191,7 +1191,7 @@ void tst_QHash::noNeedlessRehashes() void tst_QHash::const_shared_null() { QHash hash2; -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QHash hash1; hash1.setSharable(false); QVERIFY(hash1.isDetached()); diff --git a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp index d3ace40164..848fdae445 100644 --- a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp +++ b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp @@ -1027,7 +1027,7 @@ template void tst_QLinkedList::constSharedNull() const { QLinkedList list2; -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QLinkedList list1; list1.setSharable(false); QVERIFY(list1.isDetached()); @@ -1059,7 +1059,7 @@ void tst_QLinkedList::constSharedNullComplex() const void tst_QLinkedList::setSharableInt() const { -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QLinkedList orglist; orglist << 0 << 1 << 2 << 3 << 4 << 5; int size = 6; diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index 1bb31afa9c..87f0012002 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -1892,7 +1892,7 @@ template void tst_QList::constSharedNull() const { QList list2; -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QList list1; list1.setSharable(false); QVERIFY(list1.isDetached()); @@ -1926,7 +1926,7 @@ void tst_QList::constSharedNullComplex() const template void generateSetSharableData() { -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QTest::addColumn >("list"); QTest::addColumn("size"); @@ -1938,7 +1938,7 @@ void generateSetSharableData() template void runSetSharableTest() { -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QFETCH(QList, list); QFETCH(int, size); diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp index bb6535b635..1fb9dc6d7d 100644 --- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp +++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp @@ -1012,7 +1012,7 @@ void tst_QMap::qmultimap_specific() void tst_QMap::const_shared_null() { QMap map2; -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QMap map1; map1.setSharable(false); QVERIFY(map1.isDetached()); @@ -1109,7 +1109,7 @@ const T &const_(const T &t) void tst_QMap::setSharable() { -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) QMap map; map.insert(1, "um"); diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 87822bca6f..edcf4c72b6 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -431,7 +431,7 @@ void tst_QVector::copyConstructor() const QVector v2(v1); QCOMPARE(v1, v2); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section { QVector v1; @@ -595,7 +595,7 @@ void tst_QVector::append() const QVERIFY(v.size() == 3); QCOMPARE(v.at(v.size() - 1), SimpleValue::at(0)); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section { QVector v(2); @@ -930,7 +930,7 @@ void tst_QVector::eraseEmpty() const v.erase(v.begin(), v.end()); QCOMPARE(v.size(), 0); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section { QVector v; @@ -969,7 +969,7 @@ void tst_QVector::eraseEmptyReserved() const v.erase(v.begin(), v.end()); QCOMPARE(v.size(), 0); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section { QVector v; @@ -1085,7 +1085,7 @@ void tst_QVector::erase(bool shared) const if (shared) QCOMPARE(SimpleValue::vector(12), *svc.copy); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section { QVector v = SimpleValue::vector(10); @@ -1172,7 +1172,7 @@ template void tst_QVector::eraseReserved() const v.erase(v.begin() + 1, v.end() - 1); QCOMPARE(v.size(), 2); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section { QVector v(10); @@ -1907,7 +1907,7 @@ void tst_QVector::resizePOD_data() const QTest::newRow("nonEmpty") << nonEmpty << 10; QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section QVector nullNotShared; QVector emptyNotShared(0, 5); @@ -1982,7 +1982,7 @@ void tst_QVector::resizeComplexMovable_data() const QTest::newRow("nonEmpty") << nonEmpty << 10; QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section QVector nullNotShared; QVector emptyNotShared(0, 'Q'); @@ -2061,7 +2061,7 @@ void tst_QVector::resizeComplex_data() const QTest::newRow("nonEmpty") << nonEmpty << 10; QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section QVector nullNotShared; QVector emptyNotShared(0, '0'); @@ -2500,7 +2500,7 @@ void tst_QVector::initializeListCustom() void tst_QVector::const_shared_null() { QVector v2; -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section QVector v1; v1.setSharable(false); @@ -2511,7 +2511,7 @@ void tst_QVector::const_shared_null() QVERIFY(!v2.isDetached()); } -#if QT_SUPPORTS(UNSHARABLE_CONTAINERS) +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) // ### Qt6 remove this section template void tst_QVector::setSharable_data() const From 9ba296cc4cefaeb9d6c5abc2e0c0b272f2288733 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 5 May 2016 02:12:31 -0700 Subject: [PATCH 12/46] Add constants for the CoreText font weights. Incidentally, this corrects two small errors in the values of the Medium and Heavy font weights. Change-Id: I17d4410890f1f3bd1ed72e94f5ca0d43c21484e1 Reviewed-by: Konstantin Ritt --- .../fontdatabases/mac/qfontengine_coretext.mm | 61 ++++++++++++++++--- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 91bf00d1a7..703ec3a8b8 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -41,6 +41,49 @@ #include +#if defined(Q_OS_OSX) && !QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_11) +#import +#endif + +#if defined(Q_OS_IOS) && !QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_8_2) +#import +#endif + +// These are available cross platform, exported as kCTFontWeightXXX from CoreText.framework, +// but they are not documented and are not in public headers so are private API and exposed +// only through the NSFontWeightXXX and UIFontWeightXXX aliases in AppKit and UIKit (rdar://26109857) +#if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_11, __IPHONE_8_2) +#define kCTFontWeightUltraLight -0.8 +#define kCTFontWeightThin -0.6 +#define kCTFontWeightLight -0.4 +#define kCTFontWeightRegular 0 +#define kCTFontWeightMedium 0.23 +#define kCTFontWeightSemibold 0.3 +#define kCTFontWeightBold 0.4 +#define kCTFontWeightHeavy 0.56 +#define kCTFontWeightBlack 0.62 +#elif defined(Q_OS_OSX) +#define kCTFontWeightUltraLight NSFontWeightUltraLight +#define kCTFontWeightThin NSFontWeightThin +#define kCTFontWeightLight NSFontWeightLight +#define kCTFontWeightRegular NSFontWeightRegular +#define kCTFontWeightMedium NSFontWeightMedium +#define kCTFontWeightSemibold NSFontWeightSemibold +#define kCTFontWeightBold NSFontWeightBold +#define kCTFontWeightHeavy NSFontWeightHeavy +#define kCTFontWeightBlack NSFontWeightBlack +#elif defined(Q_OS_IOS) +#define kCTFontWeightUltraLight UIFontWeightUltraLight +#define kCTFontWeightThin UIFontWeightThin +#define kCTFontWeightLight UIFontWeightLight +#define kCTFontWeightRegular UIFontWeightRegular +#define kCTFontWeightMedium UIFontWeightMedium +#define kCTFontWeightSemibold UIFontWeightSemibold +#define kCTFontWeightBold UIFontWeightBold +#define kCTFontWeightHeavy UIFontWeightHeavy +#define kCTFontWeightBlack UIFontWeightBlack +#endif + QT_BEGIN_NAMESPACE static float SYNTHETIC_ITALIC_SKEW = std::tan(14.f * std::acos(0.f) / 90.f); @@ -63,23 +106,23 @@ bool QCoreTextFontEngine::ct_getSfntTable(void *user_data, uint tag, uchar *buff QFont::Weight QCoreTextFontEngine::qtWeightFromCFWeight(float value) { - if (value >= 0.62) + if (value >= kCTFontWeightBlack) return QFont::Black; - if (value >= 0.5) + if (value >= kCTFontWeightHeavy) return QFont::ExtraBold; - if (value >= 0.4) + if (value >= kCTFontWeightBold) return QFont::Bold; - if (value >= 0.3) + if (value >= kCTFontWeightSemibold) return QFont::DemiBold; - if (value >= 0.2) + if (value >= kCTFontWeightMedium) return QFont::Medium; - if (value == 0.0) + if (value == kCTFontWeightRegular) return QFont::Normal; - if (value <= -0.8) + if (value <= kCTFontWeightUltraLight) return QFont::Thin; - if (value <= -0.6) + if (value <= kCTFontWeightThin) return QFont::ExtraLight; - if (value <= -0.4) + if (value <= kCTFontWeightLight) return QFont::Light; return QFont::Normal; } From 194a56ea79a4aa11a01dda0491427bb5ba4b37fd Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 1 Dec 2015 17:44:34 -0800 Subject: [PATCH 13/46] QTest: Fix printing of values of Q_ENUMs QMetaEnum::key(n) returns the n-th key, which is not necessarily the one of value n. For the key of value n, we want QMetaEnum::valueToKey(n). Change-Id: Ic90fe6b1cbe84978a02fffff141bf4a06074917a Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/testlib/qtestcase.h | 2 +- tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp | 5 +++-- tests/auto/testlib/selftests/expected_cmptest.lightxml | 4 ++-- tests/auto/testlib/selftests/expected_cmptest.txt | 4 ++-- tests/auto/testlib/selftests/expected_cmptest.xml | 4 ++-- tests/auto/testlib/selftests/expected_cmptest.xunitxml | 4 ++-- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index 9d79439e04..14ee0865eb 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -238,7 +238,7 @@ namespace QTest inline typename QtPrivate::QEnableIf::Value, char*>::Type toString(T e) { QMetaEnum me = QMetaEnum::fromType(); - return qstrdup(me.key(int(e))); // int cast is necessary to support enum classes + return qstrdup(me.valueToKey(int(e))); // int cast is necessary to support enum classes } template // Fallback diff --git a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp index 6446fec510..09a90508d3 100644 --- a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp +++ b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp @@ -156,8 +156,9 @@ void tst_Cmptest::compare_unregistered_enums() void tst_Cmptest::compare_registered_enums() { - QCOMPARE(Qt::ArrowCursor, Qt::ArrowCursor); - QCOMPARE(Qt::ArrowCursor, Qt::BusyCursor); + // use an enum that doesn't start at 0 + QCOMPARE(Qt::Monday, Qt::Monday); + QCOMPARE(Qt::Monday, Qt::Sunday); } static bool boolfunc() { return true; } diff --git a/tests/auto/testlib/selftests/expected_cmptest.lightxml b/tests/auto/testlib/selftests/expected_cmptest.lightxml index 36929cec6b..8f02e2e1ad 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.lightxml +++ b/tests/auto/testlib/selftests/expected_cmptest.lightxml @@ -16,8 +16,8 @@ + Actual (Qt::Monday): Monday + Expected (Qt::Sunday): Sunday]]> diff --git a/tests/auto/testlib/selftests/expected_cmptest.txt b/tests/auto/testlib/selftests/expected_cmptest.txt index 70c54704f9..9205658509 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.txt +++ b/tests/auto/testlib/selftests/expected_cmptest.txt @@ -4,8 +4,8 @@ PASS : tst_Cmptest::initTestCase() FAIL! : tst_Cmptest::compare_unregistered_enums() Compared values are not the same Loc: [tst_cmptest.cpp(154)] FAIL! : tst_Cmptest::compare_registered_enums() Compared values are not the same - Actual (Qt::ArrowCursor): ArrowCursor - Expected (Qt::BusyCursor) : BusyCursor + Actual (Qt::Monday): Monday + Expected (Qt::Sunday): Sunday Loc: [tst_cmptest.cpp(160)] PASS : tst_Cmptest::compare_boolfuncs() PASS : tst_Cmptest::compare_pointerfuncs() diff --git a/tests/auto/testlib/selftests/expected_cmptest.xml b/tests/auto/testlib/selftests/expected_cmptest.xml index 9437e8e4b7..55a9706227 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.xml +++ b/tests/auto/testlib/selftests/expected_cmptest.xml @@ -18,8 +18,8 @@ + Actual (Qt::Monday): Monday + Expected (Qt::Sunday): Sunday]]> diff --git a/tests/auto/testlib/selftests/expected_cmptest.xunitxml b/tests/auto/testlib/selftests/expected_cmptest.xunitxml index fa970d4172..c26f723cfc 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.xunitxml +++ b/tests/auto/testlib/selftests/expected_cmptest.xunitxml @@ -11,8 +11,8 @@ + Actual (Qt::Monday): Monday + Expected (Qt::Sunday): Sunday" result="fail"/> From 558718ff4406638410364db7c1310cb38963d6df Mon Sep 17 00:00:00 2001 From: Vyacheslav Grigoryev Date: Fri, 6 May 2016 01:29:27 +0300 Subject: [PATCH 14/46] QTableView: Fix selection for reordered or hidden rows/columns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old code sometimes made incorrect selections when rows or columns were hidden or moved. It used logical top left and bottom right indexes to create a selection rectangle. However on moved or hidden cells a wrong rectangle was made. This fix calculates a simple rectangle without hidden cells and makes use of the row/column select functionality provided by the selection model, to make the right selection. [ChangeLog][QtWidgets][QTableView] Fixed a selection bug when rows or columns were hidden (QTBUG-50171) Task-number: QTBUG-50171 Change-Id: Id186012af26da7b2051ff5eb1c13e6b7494cca77 Reviewed-by: Thorbjørn Lund Martsum --- src/widgets/itemviews/qtableview.cpp | 23 ++++++------ .../itemviews/qtableview/tst_qtableview.cpp | 36 +++++++++++++++++++ 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index ee0d41ce15..b68c105aba 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -3249,13 +3249,12 @@ void QTableViewPrivate::selectRow(int row, bool anchor) command |= QItemSelectionModel::Current; } - QModelIndex tl = model->index(qMin(rowSectionAnchor, row), logicalColumn(0), root); - QModelIndex br = model->index(qMax(rowSectionAnchor, row), logicalColumn(model->columnCount(root) - 1), root); - if ((verticalHeader->sectionsMoved() && tl.row() != br.row()) - || horizontalHeader->sectionsMoved()) { - q->setSelection(q->visualRect(tl)|q->visualRect(br), command); + QModelIndex upper = model->index(qMin(rowSectionAnchor, row), column, root); + QModelIndex lower = model->index(qMax(rowSectionAnchor, row), column, root); + if ((verticalHeader->sectionsMoved() && upper.row() != lower.row())) { + q->setSelection(q->visualRect(upper) | q->visualRect(lower), command | QItemSelectionModel::Rows); } else { - selectionModel->select(QItemSelection(tl, br), command); + selectionModel->select(QItemSelection(upper, lower), command | QItemSelectionModel::Rows); } } } @@ -3289,14 +3288,12 @@ void QTableViewPrivate::selectColumn(int column, bool anchor) command |= QItemSelectionModel::Current; } - QModelIndex tl = model->index(logicalRow(0), qMin(columnSectionAnchor, column), root); - QModelIndex br = model->index(logicalRow(model->rowCount(root) - 1), - qMax(columnSectionAnchor, column), root); - if ((horizontalHeader->sectionsMoved() && tl.column() != br.column()) - || verticalHeader->sectionsMoved()) { - q->setSelection(q->visualRect(tl)|q->visualRect(br), command); + QModelIndex left = model->index(row, qMin(columnSectionAnchor, column), root); + QModelIndex right = model->index(row, qMax(columnSectionAnchor, column), root); + if ((horizontalHeader->sectionsMoved() && left.column() != right.column())) { + q->setSelection(q->visualRect(left) | q->visualRect(right), command | QItemSelectionModel::Columns); } else { - selectionModel->select(QItemSelection(tl, br), command); + selectionModel->select(QItemSelection(left, right), command | QItemSelectionModel::Columns); } } } diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index e5abd6bc46..2bb3f6a136 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -203,6 +203,7 @@ private slots: void taskQTBUG_8777_scrollToSpans(); void taskQTBUG_10169_sizeHintForRow(); void taskQTBUG_30653_doItemsLayout(); + void taskQTBUG_50171_selectRowAfterSwapColumns(); #ifndef QT_NO_WHEELEVENT void mouseWheel_data(); @@ -4476,5 +4477,40 @@ void tst_QTableView::taskQTBUG_30653_doItemsLayout() QCOMPARE(scrollToBottomOffset, doItemsLayoutOffset); } +void tst_QTableView::taskQTBUG_50171_selectRowAfterSwapColumns() +{ + { + QtTestTableView tableView; + QtTestTableModel model(2, 3); + tableView.setModel(&model); + + tableView.horizontalHeader()->swapSections(1, 2); + tableView.horizontalHeader()->hideSection(0); + tableView.selectRow(1); + + QItemSelectionModel* tableSelectionModel = tableView.selectionModel(); + QCOMPARE(tableSelectionModel->isRowSelected(1, QModelIndex()), true); + QCOMPARE(tableSelectionModel->isSelected(tableView.model()->index(0, 0)), false); + QCOMPARE(tableSelectionModel->isSelected(tableView.model()->index(0, 1)), false); + QCOMPARE(tableSelectionModel->isSelected(tableView.model()->index(0, 2)), false); + } + + { + QtTestTableView tableView; + QtTestTableModel model(3, 2); + tableView.setModel(&model); + + tableView.verticalHeader()->swapSections(1, 2); + tableView.verticalHeader()->hideSection(0); + tableView.selectColumn(1); + + QItemSelectionModel* sModel = tableView.selectionModel(); + QCOMPARE(sModel->isColumnSelected(1, QModelIndex()), true); + QCOMPARE(sModel->isSelected(tableView.model()->index(0, 0)), false); + QCOMPARE(sModel->isSelected(tableView.model()->index(1, 0)), false); + QCOMPARE(sModel->isSelected(tableView.model()->index(2, 0)), false); + } +} + QTEST_MAIN(tst_QTableView) #include "tst_qtableview.moc" From 8de2986a42ff452d2ca7f28d23ce1156be326b62 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 6 May 2016 23:41:14 -0700 Subject: [PATCH 15/46] tst_QDBusMarshall: make sure we compile on linked, old dbus If we're linking to libdbus-1, qdbus_symbols_p.h #includes dbus/dbus.h, which may be old and not #define the Unix FD macros. tst_QDBusMarshall had the definition for one of the macros but not the other, so add the missing second one. Change-Id: Id69569111e7d4e619e22ffff144c35edcd6f348b Reviewed-by: Frederik Gladhorn --- tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp index 57fd5084be..b628738fe3 100644 --- a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp @@ -41,6 +41,11 @@ #include #include +#ifndef DBUS_TYPE_UNIX_FD +# define DBUS_TYPE_UNIX_FD int('h') +# define DBUS_TYPE_UNIX_FD_AS_STRING "h" +#endif + static const char serviceName[] = "org.qtproject.autotests.qpong"; static const char objectPath[] = "/org/qtproject/qpong"; static const char *interfaceName = serviceName; @@ -1088,9 +1093,6 @@ static bool canSendUnixFd(DBusConnection *connection) can_send_type = (can_send_type_t)qdbus_resolve_conditionally("dbus_connection_can_send_type"); #endif -#ifndef DBUS_TYPE_UNIX_FD -# define DBUS_TYPE_UNIX_FD int('h') -#endif return can_send_type && can_send_type(connection, DBUS_TYPE_UNIX_FD); } From ad66dbe305cff72443f4d3484191872d56e6dfbb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 27 Apr 2016 22:34:26 -0700 Subject: [PATCH 16/46] Disconnect signals from each QObject only once in QDBusConnectionPrivate Because the moment we disconnect from the object's destroyed() signal, it may get destroyed in another thread. If the same object appears more than once in the object tree or in the signal hook table, we could be accessing a dangling pointer. Task-number: QTBUG-52988 Change-Id: Ifea6e497f11a461db432ffff14496f0f83889104 Reviewed-by: Weng Xuetian Reviewed-by: Thiago Macieira --- src/dbus/qdbusconnection_p.h | 2 +- src/dbus/qdbusintegrator.cpp | 29 +++++++++++++++++++---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index b733a68856..fff9f29b03 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -254,7 +254,7 @@ private: const QVector &metaTypes, int slotIdx); SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it); - void disconnectObjectTree(ObjectTreeNode &node); + void collectAllObjects(ObjectTreeNode &node, QSet &set); bool isServiceRegisteredByThread(const QString &serviceName); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index d0468f4af0..147966b9b0 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1071,17 +1071,18 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() } } -void QDBusConnectionPrivate::disconnectObjectTree(QDBusConnectionPrivate::ObjectTreeNode &haystack) +void QDBusConnectionPrivate::collectAllObjects(QDBusConnectionPrivate::ObjectTreeNode &haystack, + QSet &set) { QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = haystack.children.begin(); while (it != haystack.children.end()) { - disconnectObjectTree(*it); + collectAllObjects(*it, set); it++; } if (haystack.obj) - haystack.obj->disconnect(this); + set.insert(haystack.obj); } void QDBusConnectionPrivate::closeConnection() @@ -1110,15 +1111,23 @@ void QDBusConnectionPrivate::closeConnection() // Disconnect all signals from signal hooks and from the object tree to // avoid QObject::destroyed being sent to dbus daemon thread which has - // already quit. - SignalHookHash::iterator sit = signalHooks.begin(); - while (sit != signalHooks.end()) { - sit.value().obj->disconnect(this); - sit++; + // already quit. We need to make sure we disconnect exactly once per + // object, because if we tried a second time, we might be hitting a + // dangling pointer. + QSet allObjects; + collectAllObjects(rootNode, allObjects); + SignalHookHash::const_iterator sit = signalHooks.constBegin(); + while (sit != signalHooks.constEnd()) { + allObjects.insert(sit.value().obj); + ++sit; } - disconnectObjectTree(rootNode); - rootNode.children.clear(); // free resources + // now disconnect ourselves + QSet::const_iterator oit = allObjects.constBegin(); + while (oit != allObjects.constEnd()) { + (*oit)->disconnect(this); + ++oit; + } } void QDBusConnectionPrivate::handleDBusDisconnection() From 29076cf6cbd22e2e16a730787c79c2734655756e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 29 Apr 2016 20:52:05 -0700 Subject: [PATCH 17/46] Fix QBasicAtomicPointer::{load,store} to actually be relaxed We were using direct loading and operator=, which for everything except std::atomic was very relaxed. But std::atomic defines the direct access to actually be the least relaxed possible, under the idea that if you didn't know any better to use a member function, you probably need the most protection. So use Ops::load and Ops::store. Change-Id: Id5480807d25e49e78b79ffff144a06a2e6398576 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/thread/qbasicatomic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index c29b80d3d0..7960174277 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -249,8 +249,8 @@ public: AtomicType _q_value; - Type load() const Q_DECL_NOTHROW { return _q_value; } - void store(Type newValue) Q_DECL_NOTHROW { _q_value = newValue; } + Type load() const Q_DECL_NOTHROW { return Ops::load(_q_value); } + void store(Type newValue) Q_DECL_NOTHROW { Ops::store(_q_value, newValue); } operator Type() const Q_DECL_NOTHROW { return loadAcquire(); } Type operator=(Type newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; } From c619fc278d7e5acd8f0ae8f9e2013f351c50c355 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 25 Feb 2013 20:55:03 -0800 Subject: [PATCH 18/46] Fix moc warning detected by ICC moc.cpp(385): error #187: use of "=" where "==" may have been intended Change-Id: Ibb6ef27030762cbe4f7c7002581a0955f0f9086d Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/tools/moc/moc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 726d1972f1..7dd94cdca7 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -378,8 +378,8 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) def->isVirtual = false; def->isStatic = false; //skip modifiers and attributes - while (test(INLINE) || (test(STATIC) && (def->isStatic = true)) || - (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual + while (test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) || + (test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool templateFunction = (lookup() == TEMPLATE); def->type = parseType(); @@ -473,8 +473,8 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) def->isVirtual = false; def->isStatic = false; //skip modifiers and attributes - while (test(EXPLICIT) || test(INLINE) || (test(STATIC) && (def->isStatic = true)) || - (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual + while (test(EXPLICIT) || test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) || + (test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool tilde = test(TILDE); def->type = parseType(); From fe23db053a5b3f2097b332ad3269cd0eb5a55168 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 18 Mar 2016 20:29:51 -0700 Subject: [PATCH 19/46] Add an autotest for the QtDBus message spy hook There's exactly one application that needs this functionality (kded/ kiod), but we should test it too. Change-Id: Icaa7fb2a490246bda156ffff143d210c6f5f207f Reviewed-by: David Faure --- tests/auto/dbus/dbus.pro | 1 + .../qdbusconnection/tst_qdbusconnection.cpp | 139 +++++++++++++++++- .../qdbusconnection/tst_qdbusconnection.h | 9 +- .../qdbusconnection_spyhook.pro | 7 + .../tst_qdbusconnection_spyhook.cpp | 57 +++++++ 5 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 tests/auto/dbus/qdbusconnection_spyhook/qdbusconnection_spyhook.pro create mode 100644 tests/auto/dbus/qdbusconnection_spyhook/tst_qdbusconnection_spyhook.cpp diff --git a/tests/auto/dbus/dbus.pro b/tests/auto/dbus/dbus.pro index 67cbc4bfef..c5cddee5f5 100644 --- a/tests/auto/dbus/dbus.pro +++ b/tests/auto/dbus/dbus.pro @@ -11,6 +11,7 @@ SUBDIRS+=\ qdbusconnection_no_app \ qdbusconnection_no_bus \ qdbusconnection_no_libdbus \ + qdbusconnection_spyhook \ qdbuscontext \ qdbusinterface \ qdbuslocalcalls \ diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index f378091c58..9b16cf74a5 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2015 Intel Corporation. +** Copyright (C) 2016 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -55,6 +55,31 @@ void MyObjectWithoutInterface::method(const QDBusMessage &msg) //qDebug() << msg; } +int tst_QDBusConnection::hookCallCount; +tst_QDBusConnection::tst_QDBusConnection() +{ +#ifdef HAS_HOOKSETUPFUNCTION +# define QCOMPARE_HOOKCOUNT(n) QCOMPARE(hookCallCount, n); hookCallCount = 0 +# define QVERIFY_HOOKCALLED() QCOMPARE(hookCallCount, 1); hookCallCount = 0 + hookSetupFunction(); +#else +# define QCOMPARE_HOOKCOUNT(n) qt_noop() +# define QVERIFY_HOOKCALLED() qt_noop() +#endif +} + +// called before each testcase +void tst_QDBusConnection::init() +{ + hookCallCount = 0; +} + +void tst_QDBusConnection::cleanup() +{ + QVERIFY2(!hookCallCount, "Unchecked call"); +} + + void tst_QDBusConnection::noConnection() { QDBusConnection con = QDBusConnection::connectToBus("unix:path=/dev/null", "testconnection"); @@ -359,9 +384,11 @@ void tst_QDBusConnection::registerObject() QCOMPARE(con.objectRegisteredAt(path), static_cast(&obj)); QVERIFY(callMethod(con, path)); QCOMPARE(obj.path, path); + QVERIFY_HOOKCALLED(); } // make sure it's gone QVERIFY(!callMethod(con, path)); + QVERIFY_HOOKCALLED(); } void tst_QDBusConnection::registerObjectWithInterface_data() @@ -393,9 +420,11 @@ void tst_QDBusConnection::registerObjectWithInterface() QVERIFY(callMethod(con, path, interface)); QCOMPARE(obj.path, path); QCOMPARE(obj.interface, interface); + QVERIFY_HOOKCALLED(); } // make sure it's gone QVERIFY(!callMethod(con, path, interface)); + QVERIFY_HOOKCALLED(); } void tst_QDBusConnection::registerObjectPeer_data() @@ -432,6 +461,7 @@ void tst_QDBusConnection::registerObjectPeer() MyObject obj; QVERIFY(callMethodPeer(con, path)); QCOMPARE(obj.path, path); + QVERIFY_HOOKCALLED(); } QDBusConnection::connectToPeer(server.address(), "afterFoo"); @@ -441,6 +471,7 @@ void tst_QDBusConnection::registerObjectPeer() QDBusConnection con("foo"); QVERIFY(con.isConnected()); QVERIFY(callMethodPeer(con, path)); + QVERIFY_HOOKCALLED(); } server.unregisterObject(); @@ -449,6 +480,7 @@ void tst_QDBusConnection::registerObjectPeer() QDBusConnection con("foo"); QVERIFY(con.isConnected()); QVERIFY(!callMethodPeer(con, path)); + QVERIFY_HOOKCALLED(); } server.registerObject(); @@ -457,6 +489,7 @@ void tst_QDBusConnection::registerObjectPeer() QDBusConnection con("foo"); QVERIFY(con.isConnected()); QVERIFY(callMethodPeer(con, path)); + QVERIFY_HOOKCALLED(); } QDBusConnection::disconnectFromPeer("foo"); @@ -478,10 +511,15 @@ void tst_QDBusConnection::registerObject2() // make sure nothing is using our paths: QVERIFY(!callMethod(con, "/")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p2")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/q")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/q/r")); + QVERIFY_HOOKCALLED(); { // register one object at root: @@ -489,76 +527,99 @@ void tst_QDBusConnection::registerObject2() QVERIFY(con.registerObject("/", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethod(con, "/")); QCOMPARE(obj.path, QString("/")); + QVERIFY_HOOKCALLED(); } // make sure it's gone QVERIFY(!callMethod(con, "/")); + QVERIFY_HOOKCALLED(); { // register one at an element: MyObject obj; QVERIFY(con.registerObject("/p1", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(!callMethod(con, "/")); + QVERIFY_HOOKCALLED(); QVERIFY(callMethod(con, "/p1")); QCOMPARE(obj.path, QString("/p1")); + QVERIFY_HOOKCALLED(); // re-register it somewhere else QVERIFY(con.registerObject("/p2", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethod(con, "/p1")); QCOMPARE(obj.path, QString("/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(callMethod(con, "/p2")); QCOMPARE(obj.path, QString("/p2")); + QVERIFY_HOOKCALLED(); } // make sure it's gone QVERIFY(!callMethod(con, "/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p2")); + QVERIFY_HOOKCALLED(); { // register at a deep path MyObject obj; QVERIFY(con.registerObject("/p1/q/r", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(!callMethod(con, "/")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/q")); + QVERIFY_HOOKCALLED(); QVERIFY(callMethod(con, "/p1/q/r")); QCOMPARE(obj.path, QString("/p1/q/r")); + QVERIFY_HOOKCALLED(); } + // make sure it's gone QVERIFY(!callMethod(con, "/p1/q/r")); + QVERIFY_HOOKCALLED(); { MyObject obj; QVERIFY(con.registerObject("/p1/q2", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethod(con, "/p1/q2")); QCOMPARE(obj.path, QString("/p1/q2")); + QVERIFY_HOOKCALLED(); // try unregistering con.unregisterObject("/p1/q2"); QVERIFY(!callMethod(con, "/p1/q2")); + QVERIFY_HOOKCALLED(); // register it again QVERIFY(con.registerObject("/p1/q2", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethod(con, "/p1/q2")); QCOMPARE(obj.path, QString("/p1/q2")); + QVERIFY_HOOKCALLED(); // now try removing things around it: con.unregisterObject("/p2"); QVERIFY(callMethod(con, "/p1/q2")); // unrelated object shouldn't affect + QVERIFY_HOOKCALLED(); con.unregisterObject("/p1"); QVERIFY(callMethod(con, "/p1/q2")); // unregistering just the parent shouldn't affect it + QVERIFY_HOOKCALLED(); con.unregisterObject("/p1/q2/r"); QVERIFY(callMethod(con, "/p1/q2")); // unregistering non-existing child shouldn't affect it either + QVERIFY_HOOKCALLED(); con.unregisterObject("/p1/q"); QVERIFY(callMethod(con, "/p1/q2")); // unregistering sibling (before) shouldn't affect + QVERIFY_HOOKCALLED(); con.unregisterObject("/p1/r"); QVERIFY(callMethod(con, "/p1/q2")); // unregistering sibling (after) shouldn't affect + QVERIFY_HOOKCALLED(); // now remove it: con.unregisterObject("/p1", QDBusConnection::UnregisterTree); QVERIFY(!callMethod(con, "/p1/q2")); // we removed the full tree + QVERIFY_HOOKCALLED(); } } @@ -577,10 +638,15 @@ void tst_QDBusConnection::registerObjectPeer2() // make sure nothing is using our paths: QVERIFY(!callMethodPeer(srv_con, "/")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p2")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/q")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/q/r")); + QVERIFY_HOOKCALLED(); { // register one object at root: @@ -588,76 +654,101 @@ void tst_QDBusConnection::registerObjectPeer2() QVERIFY(con.registerObject("/", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethodPeer(srv_con, "/")); QCOMPARE(obj.path, QString("/")); + QVERIFY_HOOKCALLED(); } + // make sure it's gone QVERIFY(!callMethodPeer(srv_con, "/")); + QVERIFY_HOOKCALLED(); { // register one at an element: MyObject obj; QVERIFY(con.registerObject("/p1", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(!callMethodPeer(srv_con, "/")); + QVERIFY_HOOKCALLED(); QVERIFY(callMethodPeer(srv_con, "/p1")); QCOMPARE(obj.path, QString("/p1")); + QVERIFY_HOOKCALLED(); // re-register it somewhere else QVERIFY(con.registerObject("/p2", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethodPeer(srv_con, "/p1")); QCOMPARE(obj.path, QString("/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(callMethodPeer(srv_con, "/p2")); QCOMPARE(obj.path, QString("/p2")); + QVERIFY_HOOKCALLED(); } + // make sure it's gone QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p2")); + QVERIFY_HOOKCALLED(); { // register at a deep path MyObject obj; QVERIFY(con.registerObject("/p1/q/r", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(!callMethodPeer(srv_con, "/")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/q")); + QVERIFY_HOOKCALLED(); QVERIFY(callMethodPeer(srv_con, "/p1/q/r")); QCOMPARE(obj.path, QString("/p1/q/r")); + QVERIFY_HOOKCALLED(); } + // make sure it's gone QVERIFY(!callMethodPeer(srv_con, "/p1/q/r")); + QVERIFY_HOOKCALLED(); { MyObject obj; QVERIFY(con.registerObject("/p1/q2", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethodPeer(srv_con, "/p1/q2")); QCOMPARE(obj.path, QString("/p1/q2")); + QVERIFY_HOOKCALLED(); // try unregistering con.unregisterObject("/p1/q2"); QVERIFY(!callMethodPeer(srv_con, "/p1/q2")); + QVERIFY_HOOKCALLED(); // register it again QVERIFY(con.registerObject("/p1/q2", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethodPeer(srv_con, "/p1/q2")); QCOMPARE(obj.path, QString("/p1/q2")); + QVERIFY_HOOKCALLED(); // now try removing things around it: con.unregisterObject("/p2"); QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unrelated object shouldn't affect + QVERIFY_HOOKCALLED(); con.unregisterObject("/p1"); QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering just the parent shouldn't affect it + QVERIFY_HOOKCALLED(); con.unregisterObject("/p1/q2/r"); QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering non-existing child shouldn't affect it either + QVERIFY_HOOKCALLED(); con.unregisterObject("/p1/q"); QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering sibling (before) shouldn't affect + QVERIFY_HOOKCALLED(); con.unregisterObject("/p1/r"); QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering sibling (after) shouldn't affect + QVERIFY_HOOKCALLED(); // now remove it: con.unregisterObject("/p1", QDBusConnection::UnregisterTree); QVERIFY(!callMethodPeer(srv_con, "/p1/q2")); // we removed the full tree + QVERIFY_HOOKCALLED(); } QDBusConnection::disconnectFromPeer("foo"); @@ -669,6 +760,7 @@ void tst_QDBusConnection::registerQObjectChildren() // make sure no one is there QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(!callMethod(con, "/p1")); + QVERIFY_HOOKCALLED(); { MyObject obj, *a, *b, *c, *cc; @@ -691,32 +783,47 @@ void tst_QDBusConnection::registerQObjectChildren() // make calls QVERIFY(callMethod(con, "/p1")); QCOMPARE(obj.callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(callMethod(con, "/p1/a")); QCOMPARE(a->callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(callMethod(con, "/p1/b")); QCOMPARE(b->callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(callMethod(con, "/p1/c")); QCOMPARE(c->callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(callMethod(con, "/p1/c/cc")); QCOMPARE(cc->callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/d")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/c/abc")); + QVERIFY_HOOKCALLED(); // pull an object, see if it goes away: delete b; QVERIFY(!callMethod(con, "/p1/b")); + QVERIFY_HOOKCALLED(); delete c; QVERIFY(!callMethod(con, "/p1/c")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/c/cc")); + QVERIFY_HOOKCALLED(); } QVERIFY(!callMethod(con, "/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/a")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/b")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/c")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethod(con, "/p1/c/cc")); + QVERIFY_HOOKCALLED(); } void tst_QDBusConnection::registerQObjectChildrenPeer() @@ -734,6 +841,7 @@ void tst_QDBusConnection::registerQObjectChildrenPeer() QDBusConnection srv_con = server.connection(); QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY_HOOKCALLED(); { MyObject obj, *a, *b, *c, *cc; @@ -756,32 +864,47 @@ void tst_QDBusConnection::registerQObjectChildrenPeer() // make calls QVERIFY(callMethodPeer(srv_con, "/p1")); QCOMPARE(obj.callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(callMethodPeer(srv_con, "/p1/a")); QCOMPARE(a->callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(callMethodPeer(srv_con, "/p1/b")); QCOMPARE(b->callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(callMethodPeer(srv_con, "/p1/c")); QCOMPARE(c->callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(callMethodPeer(srv_con, "/p1/c/cc")); QCOMPARE(cc->callCount, 1); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/d")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/c/abc")); + QVERIFY_HOOKCALLED(); // pull an object, see if it goes away: delete b; QVERIFY(!callMethodPeer(srv_con, "/p1/b")); + QVERIFY_HOOKCALLED(); delete c; QVERIFY(!callMethodPeer(srv_con, "/p1/c")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/c/cc")); + QVERIFY_HOOKCALLED(); } QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/a")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/b")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/c")); + QVERIFY_HOOKCALLED(); QVERIFY(!callMethodPeer(srv_con, "/p1/c/cc")); + QVERIFY_HOOKCALLED(); QDBusConnection::disconnectFromPeer("foo"); } @@ -827,20 +950,25 @@ void tst_QDBusConnection::callSelf() QVERIFY(connection.registerService(serviceName())); QDBusInterface interface(serviceName(), "/test"); QVERIFY(interface.isValid()); + QVERIFY_HOOKCALLED(); interface.call(QDBus::Block, "test0"); QCOMPARE(testObject.func, QString("test0")); + QVERIFY_HOOKCALLED(); interface.call(QDBus::Block, "test1", 42); QCOMPARE(testObject.func, QString("test1 42")); + QVERIFY_HOOKCALLED(); QDBusMessage reply = interface.call(QDBus::Block, "test2"); QCOMPARE(testObject.func, QString("test2")); QCOMPARE(reply.arguments().value(0).toInt(), 43); + QVERIFY_HOOKCALLED(); QDBusMessage msg = QDBusMessage::createMethodCall(serviceName(), "/test", QString(), "test3"); msg << 44; reply = connection.call(msg); QCOMPARE(reply.arguments().value(0).toInt(), 45); + QVERIFY_HOOKCALLED(); } void tst_QDBusConnection::callSelfByAnotherName_data() @@ -908,12 +1036,14 @@ void tst_QDBusConnection::callSelfByAnotherName() QDBusMessage reply = con.call(msg, QDBus::Block, 1000); QVERIFY(reply.type() == QDBusMessage::ReplyMessage); + QVERIFY_HOOKCALLED(); } void tst_QDBusConnection::multipleInterfacesInQObject() { QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(!callMethod(con, "/p1")); + QVERIFY_HOOKCALLED(); MyObject obj; con.registerObject("/p1", &obj, QDBusConnection::ExportAllSlots); @@ -924,6 +1054,7 @@ void tst_QDBusConnection::multipleInterfacesInQObject() QDBusMessage reply = con.call(msg, QDBus::Block); QCOMPARE(reply.type(), QDBusMessage::ReplyMessage); QVERIFY(reply.arguments().count() == 0); + QVERIFY_HOOKCALLED(); } void tst_QDBusConnection::slotsWithLessParameters() @@ -981,6 +1112,7 @@ void tst_QDBusConnection::nestedCallWithCallback() QTestEventLoop::instance().enterLoop(15); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(signalsReceived, 1); + QCOMPARE_HOOKCOUNT(2); } void tst_QDBusConnection::serviceRegistrationRaceCondition() @@ -1145,6 +1277,7 @@ void tst_QDBusConnection::callVirtualObject() QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY_HOOKCALLED(); QCOMPARE(obj.callCount, 1); QCOMPARE(obj.lastMessage.service(), con2.baseService()); @@ -1162,6 +1295,7 @@ void tst_QDBusConnection::callVirtualObject() QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY_HOOKCALLED(); QCOMPARE(obj.callCount, 2); QCOMPARE(obj.lastMessage.service(), con2.baseService()); @@ -1179,6 +1313,7 @@ void tst_QDBusConnection::callVirtualObject() QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY_HOOKCALLED(); QTest::qWait(100); QVERIFY(errorReply.isError()); QCOMPARE(errorReply.reply().errorName(), QString("org.freedesktop.DBus.Error.UnknownObject")); @@ -1207,6 +1342,7 @@ void tst_QDBusConnection::callVirtualObjectLocal() QCOMPARE(obj.lastMessage.interface(), QString()); QCOMPARE(obj.lastMessage.path(), path); QCOMPARE(obj.replyArguments, reply.arguments()); + QVERIFY_HOOKCALLED(); obj.replyArguments << QString("alien abduction"); QDBusMessage subPathMessage = QDBusMessage::createMethodCall(con.baseService(), childPath, QString(), "hello"); @@ -1216,6 +1352,7 @@ void tst_QDBusConnection::callVirtualObjectLocal() QCOMPARE(obj.lastMessage.interface(), QString()); QCOMPARE(obj.lastMessage.path(), childPath); QCOMPARE(obj.replyArguments, subPathReply.arguments()); + QVERIFY_HOOKCALLED(); } void tst_QDBusConnection::pendingCallWhenDisconnected() diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h index 720e484cc2..b47daa118b 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2015 Intel Corporation. +** Copyright (C) 2016 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -79,11 +79,18 @@ class tst_QDBusConnection: public QObject Q_OBJECT int signalsReceived; +public: + static int hookCallCount; + tst_QDBusConnection(); + public slots: void oneSlot() { ++signalsReceived; } void exitLoop() { ++signalsReceived; QTestEventLoop::instance().exitLoop(); } void secondCallWithCallback(); + void init(); + void cleanup(); + private slots: void noConnection(); void connectToBus(); diff --git a/tests/auto/dbus/qdbusconnection_spyhook/qdbusconnection_spyhook.pro b/tests/auto/dbus/qdbusconnection_spyhook/qdbusconnection_spyhook.pro new file mode 100644 index 0000000000..020d30380d --- /dev/null +++ b/tests/auto/dbus/qdbusconnection_spyhook/qdbusconnection_spyhook.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +TARGET = tst_qdbusconnection_spyhook +QT = core dbus testlib +SOURCES += tst_qdbusconnection_spyhook.cpp +HEADERS += ../qdbusconnection/tst_qdbusconnection.h +DEFINES += SRCDIR=\\\"$$PWD/\\\" tst_QDBusConnection=tst_QDBusConnection_SpyHook +include(../dbus-testcase.pri) diff --git a/tests/auto/dbus/qdbusconnection_spyhook/tst_qdbusconnection_spyhook.cpp b/tests/auto/dbus/qdbusconnection_spyhook/tst_qdbusconnection_spyhook.cpp new file mode 100644 index 0000000000..fa1c19920a --- /dev/null +++ b/tests/auto/dbus/qdbusconnection_spyhook/tst_qdbusconnection_spyhook.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#define HAS_HOOKSETUPFUNCTION 1 +static void hookSetupFunction(); + +// Ugly hack, look away +#include "../qdbusconnection/tst_qdbusconnection.cpp" + +QT_BEGIN_NAMESPACE +extern Q_DBUS_EXPORT void qDBusAddSpyHook(void (*Hook)(const QDBusMessage&)); +QT_END_NAMESPACE + +static void hookFunction(const QDBusMessage &) +{ +// qDebug() << "hook called"; + ++tst_QDBusConnection::hookCallCount; +} + +static void hookSetupFunction() +{ + QT_PREPEND_NAMESPACE(qDBusAddSpyHook)(hookFunction); +} + +QTEST_MAIN(tst_QDBusConnection_SpyHook) From b168c6c8248662da31dbaaf2afb8e771a9ecdc85 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 17 Nov 2015 22:21:53 -0800 Subject: [PATCH 20/46] QStorageInfo: fix matching of mountpoints to sibling directories The path "/usrfoo" starts with "/usr", so if you tried to get QStorageInfo("/usrfoo") when "/usr" is a mount point, you'd get the wrong filesystem. [ChangeLog][QtCore][QStorageInfo] Fixed a bug that caused QStorageInfo to report information for the wrong filesystem if there is a mounted filesystem at a path that is a prefix of the requested path (e.g., it would report "/usr" filesystem for "/usrfoo"). Task-number: QTBUG-49498 Change-Id: I3e15a26e0e424169ac2bffff1417b7a27cd0132d Reviewed-by: Jake Petroules --- src/corelib/io/qstorageinfo_unix.cpp | 58 +++++++------ .../io/qstorageinfo/tst_qstorageinfo.cpp | 2 + tests/manual/manual.pro | 1 + tests/manual/qstorageinfo/main.cpp | 81 +++++++++++++++++++ tests/manual/qstorageinfo/qstorageinfo.pro | 4 + 5 files changed, 122 insertions(+), 24 deletions(-) create mode 100644 tests/manual/qstorageinfo/main.cpp create mode 100644 tests/manual/qstorageinfo/qstorageinfo.pro diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index e365d8d7e6..bbcc29c50b 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -102,25 +102,6 @@ QT_BEGIN_NAMESPACE -static bool isPseudoFs(const QString &mountDir, const QByteArray &type) -{ - if (mountDir.startsWith(QLatin1String("/dev")) - || mountDir.startsWith(QLatin1String("/proc")) - || mountDir.startsWith(QLatin1String("/sys")) - || mountDir.startsWith(QLatin1String("/var/run")) - || mountDir.startsWith(QLatin1String("/var/lock"))) { - return true; - } - if (type == "tmpfs") - return true; -#if defined(Q_OS_LINUX) - if (type == "rootfs" || type == "rpc_pipefs") - return true; -#endif - - return false; -} - class QStorageIterator { public: @@ -158,6 +139,36 @@ private: #endif }; +template +static bool isParentOf(const String &parent, const QString &dirName) +{ + return dirName.startsWith(parent) && + (dirName.size() == parent.size() || dirName.at(parent.size()) == QLatin1Char('/') || + parent.size() == 1); +} + +static bool isPseudoFs(const QStorageIterator &it) +{ + QString mountDir = it.rootPath(); + if (isParentOf(QLatin1String("/dev"), mountDir) + || isParentOf(QLatin1String("/proc"), mountDir) + || isParentOf(QLatin1String("/sys"), mountDir) + || isParentOf(QLatin1String("/var/run"), mountDir) + || isParentOf(QLatin1String("/var/lock"), mountDir)) { + return true; + } + + QByteArray type = it.fileSystemType(); + if (type == "tmpfs") + return true; +#if defined(Q_OS_LINUX) + if (type == "rootfs" || type == "rpc_pipefs") + return true; +#endif + + return false; +} + #if defined(Q_OS_BSD4) inline QStorageIterator::QStorageIterator() @@ -444,10 +455,10 @@ void QStorageInfoPrivate::initRootPath() while (it.next()) { const QString mountDir = it.rootPath(); const QByteArray fsName = it.fileSystemType(); - if (isPseudoFs(mountDir, fsName)) + if (isPseudoFs(it)) continue; // we try to find most suitable entry - if (oldRootPath.startsWith(mountDir) && maxLength < mountDir.length()) { + if (isParentOf(mountDir, oldRootPath) && maxLength < mountDir.length()) { maxLength = mountDir.length(); rootPath = mountDir; device = it.device(); @@ -536,11 +547,10 @@ QList QStorageInfoPrivate::mountedVolumes() QList volumes; while (it.next()) { - const QString mountDir = it.rootPath(); - const QByteArray fsName = it.fileSystemType(); - if (isPseudoFs(mountDir, fsName)) + if (isPseudoFs(it)) continue; + const QString mountDir = it.rootPath(); volumes.append(QStorageInfo(mountDir)); } diff --git a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp index efbcdc78e0..1afcf05135 100644 --- a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp +++ b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp @@ -162,6 +162,7 @@ void tst_QStorageInfo::tempFile() #endif qint64 free = storage1.bytesFree(); + QVERIFY(free != -1); file.write(QByteArray(1024*1024, '1')); file.flush(); @@ -185,6 +186,7 @@ void tst_QStorageInfo::caching() qint64 free = storage1.bytesFree(); QStorageInfo storage2(storage1); QVERIFY(free == storage2.bytesFree()); + QVERIFY(free != -1); file.write(QByteArray(1024*1024, '\0')); file.flush(); diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index bec098d462..8e77a321dd 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -24,6 +24,7 @@ qnetworkaccessmanager/qget \ qnetworkconfigurationmanager \ qnetworkconfiguration \ qnetworkreply \ +qstorageinfo \ qscreen \ qssloptions \ qsslsocket \ diff --git a/tests/manual/qstorageinfo/main.cpp b/tests/manual/qstorageinfo/main.cpp new file mode 100644 index 0000000000..884e5559ce --- /dev/null +++ b/tests/manual/qstorageinfo/main.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + QList volumes; + QStringList args = a.arguments(); + args.takeFirst(); // skip application name + + foreach (const QString &path, args) { + QStorageInfo info(path); + if (!info.isValid()) { + // no error string... + fprintf(stderr, "Could not get info on %s\n", qPrintable(path)); + return 1; + } + volumes << info; + } + + if (volumes.isEmpty()) + volumes = QStorageInfo::mountedVolumes(); + + // Sample output: + // Filesystem (Type) Size Available BSize Label Mounted on + // /dev/sda2 (ext4) RO 388480 171218 1024 /boot + // /dev/mapper/system-root (btrfs) RW + // 214958080 39088272 4096 / + // /dev/disk1s2 (hfs) RW 488050672 419909696 4096 Macintosh HD2 /Volumes/Macintosh HD2 + + printf("Filesystem (Type) Size Available BSize Label Mounted on\n"); + foreach (const QStorageInfo &info, volumes) { + const QString fsAndType = info.device() + QLatin1String(" (") + + info.fileSystemType() + QLatin1Char(')'); + + printf("%-19s R%c ", qPrintable(fsAndType), info.isReadOnly() ? 'O' : 'W'); + if (fsAndType.size() > 19) + printf("\n%23s", ""); + + printf("%10llu %10llu %5u ", info.bytesTotal() / 1024, info.bytesFree() / 1024, info.blockSize()); + printf("%-16s %s\n", qPrintable(info.name()), qPrintable(info.rootPath())); + } + + return 0; +} diff --git a/tests/manual/qstorageinfo/qstorageinfo.pro b/tests/manual/qstorageinfo/qstorageinfo.pro new file mode 100644 index 0000000000..25acd24c80 --- /dev/null +++ b/tests/manual/qstorageinfo/qstorageinfo.pro @@ -0,0 +1,4 @@ +QT = core +CONFIG += console +CONFIG -= app_bundle +SOURCES += main.cpp From d9f6b6d1f836c25a8179ae7a6df18ee9cceebfb1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 17 Nov 2015 22:25:04 -0800 Subject: [PATCH 21/46] QStorageInfo: update the detection of pseudo filesystems Allow tmpfs filesystems to be reported, as they're often usable by the user, mounted in /tmp and in /run (the fs for $XDG_RUNTIME_DIR). But disallow anything whose device is not a pathname. This catches most of everything else that wasn't specifically tested for before, like virtual fuse filesystems, like GVFS. Change-Id: I3e15a26e0e424169ac2bffff1417b7cee0f8ec97 Reviewed-by: Ivan Komissarov Reviewed-by: Thiago Macieira --- src/corelib/io/qstorageinfo_unix.cpp | 5 ++++- tests/manual/qstorageinfo/main.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index bbcc29c50b..bf998993d8 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -160,12 +160,15 @@ static bool isPseudoFs(const QStorageIterator &it) QByteArray type = it.fileSystemType(); if (type == "tmpfs") - return true; + return false; #if defined(Q_OS_LINUX) if (type == "rootfs" || type == "rpc_pipefs") return true; #endif + if (!it.device().startsWith('/')) + return true; + return false; } diff --git a/tests/manual/qstorageinfo/main.cpp b/tests/manual/qstorageinfo/main.cpp index 884e5559ce..5c106ff45b 100644 --- a/tests/manual/qstorageinfo/main.cpp +++ b/tests/manual/qstorageinfo/main.cpp @@ -66,10 +66,11 @@ int main(int argc, char *argv[]) printf("Filesystem (Type) Size Available BSize Label Mounted on\n"); foreach (const QStorageInfo &info, volumes) { - const QString fsAndType = info.device() + QLatin1String(" (") + - info.fileSystemType() + QLatin1Char(')'); + QByteArray fsAndType = info.device(); + if (info.fileSystemType() != fsAndType) + fsAndType += " (" + info.fileSystemType() + ')'; - printf("%-19s R%c ", qPrintable(fsAndType), info.isReadOnly() ? 'O' : 'W'); + printf("%-19s R%c ", fsAndType.constData(), info.isReadOnly() ? 'O' : 'W'); if (fsAndType.size() > 19) printf("\n%23s", ""); From 4aba3dbcb3832cb70253b7100e2a8555261a69c8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 17 Nov 2015 22:54:19 -0800 Subject: [PATCH 22/46] QStorageInfo: get the label properly if the mounted device is a symlink This happens for me with LVM: $ ls -l /dev/mapper/system-root /dev/system/root /dev/disk/by-label/* lrwxrwxrwx 1 root root 10 Nov 17 22:45 /dev/disk/by-label/system -> ../../dm-1 lrwxrwxrwx 1 root root 7 Nov 17 22:45 /dev/mapper/system-root -> ../dm-1 lrwxrwxrwx 1 root root 7 Nov 17 22:45 /dev/system/root -> ../dm-1 The mounted device according to /etc/mtab (/proc/self/mounts) is /dev/mapper/system-root. Change-Id: I3e15a26e0e424169ac2bffff1417b96779d84246 Reviewed-by: Ivan Komissarov Reviewed-by: Thiago Macieira --- src/corelib/io/qstorageinfo_unix.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index bf998993d8..bf33c160fc 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -475,11 +475,14 @@ static inline QString retrieveLabel(const QByteArray &device) #ifdef Q_OS_LINUX static const char pathDiskByLabel[] = "/dev/disk/by-label"; + QFileInfo devinfo(QFile::decodeName(device)); + QString devicePath = devinfo.canonicalFilePath(); + QDirIterator it(QLatin1String(pathDiskByLabel), QDir::NoDotAndDotDot); while (it.hasNext()) { it.next(); QFileInfo fileInfo(it.fileInfo()); - if (fileInfo.isSymLink() && fileInfo.symLinkTarget().toLocal8Bit() == device) + if (fileInfo.isSymLink() && fileInfo.symLinkTarget() == devicePath) return fileInfo.fileName(); } #elif defined Q_OS_HAIKU From 0453897f1ee1cdf6dc216bec975a198e386428e6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 17 Nov 2015 23:07:49 -0800 Subject: [PATCH 23/46] QStorageInfo: allow getting the info of pseudo filesystems too They won't be listed in QStorageInfo::mountedVolumes, but we can now obtain their info if you know their mountpoint. For example, on Linux: $ ./qstorageinfo /dev /proc /sys Filesystem (Type) Size Available BSize Label Mounted on devtmpfs (devtmpfs) RW 4029772 4029764 4096 /dev proc (proc) RW 0 0 4096 /proc sysfs (sysfs) RW 0 0 4096 /sys Change-Id: I3e15a26e0e424169ac2bffff1417ba2429d6d9f4 Reviewed-by: Ivan Komissarov Reviewed-by: Thiago Macieira --- src/corelib/io/qstorageinfo_unix.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index bf33c160fc..1d1b2907b7 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -458,8 +458,6 @@ void QStorageInfoPrivate::initRootPath() while (it.next()) { const QString mountDir = it.rootPath(); const QByteArray fsName = it.fileSystemType(); - if (isPseudoFs(it)) - continue; // we try to find most suitable entry if (isParentOf(mountDir, oldRootPath) && maxLength < mountDir.length()) { maxLength = mountDir.length(); From c0425f39d12a63238532e6e9c6634628bf1ed2de Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 9 May 2016 09:45:49 +0200 Subject: [PATCH 24/46] Windows Accessibility: Use QWindowsAccessibility::windowHelper(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amends changes ee516381873857e833b53b175fd3c40e4c45a5fd, d7a3b6145999d015997e26e12a7345f774b053f3. Task-number: QTBUG-52943 Change-Id: Icdf9d99c327bdd38dfb084e6cf77b14cd5ce073b Reviewed-by: Jan Arve Sæther --- .../windows/accessible/qwindowsmsaaaccessible.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 71c197a32c..5550dd4efd 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -470,15 +470,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::Invoke(long dispIdMember, return hr; } -static const QWindow *windowOf(const QAccessibleInterface *ai) -{ - for ( ; ai; ai = ai->parent()) { - if (const QWindow *window = ai->window()) - return window; - } - return Q_NULLPTR; -} - /* IAccessible @@ -507,7 +498,8 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yT if (!accessible) return E_FAIL; - const QPoint pos = QHighDpi::fromNativeLocalPosition(QPoint(xLeft, yTop), windowOf(accessible)); + const QPoint pos = QHighDpi::fromNativeLocalPosition(QPoint(xLeft, yTop), + QWindowsAccessibility::windowHelper(accessible)); QAccessibleInterface *child = accessible->childAt(pos.x(), pos.y()); if (child == 0) { // no child found, return this item if it contains the coordinates @@ -550,7 +542,8 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long QAccessibleInterface *acc = childPointer(accessible, varID); if (!acc || !acc->isValid()) return E_FAIL; - const QRect rect = QHighDpi::toNativePixels(acc->rect(), windowOf(accessible)); + const QRect rect = QHighDpi::toNativePixels(acc->rect(), + QWindowsAccessibility::windowHelper(accessible)); *pxLeft = rect.x(); *pyTop = rect.y(); From 9f6f06c31906c5261e578d742c48f39c0d867f37 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 9 May 2016 10:32:37 +0200 Subject: [PATCH 25/46] tst_QMdiArea::subWindowActivated2(): Allow for several activated events. On some X11 window managers, 2 events are received when hiding/reshowing and activating the window, which became apparent after 91f536dd71cd154675264c27273020f4de310ec2. Change-Id: I66fdc4f69d87ac898b18d5dfddc957617bb8f916 Reviewed-by: Simon Hausmann --- tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index 57be110c15..f832ebfee0 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -499,7 +499,7 @@ void tst_QMdiArea::subWindowActivated2() mdiArea.show(); mdiArea.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&mdiArea)); - QTRY_COMPARE(spy.count(), 1); + QTRY_VERIFY(!spy.isEmpty()); // Normally 1, but 2 events might be received on some X11 window managers QVERIFY(mdiArea.currentSubWindow()); QTRY_COMPARE(mdiArea.activeSubWindow(), activeSubWindow); spy.clear(); From ed7845098f59e5d4df7af681bc15777c0e4ca1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A4=C3=A4tt=C3=A4=20Antti?= Date: Mon, 9 May 2016 12:58:38 +0300 Subject: [PATCH 26/46] Fix threading issue in creating static opengl context Add mutex lock for static opengl context creation. Task-number: QTBUG-53202 Change-Id: Iba22339776ec8885efd82b13ae56f6781a426f4b Reviewed-by: Laszlo Agocs --- src/plugins/platforms/windows/qwindowsintegration.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 3966a4cd77..968ef7bd3b 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -139,7 +139,8 @@ struct QWindowsIntegrationPrivate # endif #endif #ifndef QT_NO_OPENGL - QSharedPointer m_staticOpenGLContext; + QMutex m_staticContextLock; + QScopedPointer m_staticOpenGLContext; #endif // QT_NO_OPENGL QScopedPointer m_inputContext; #ifndef QT_NO_ACCESSIBILITY @@ -435,8 +436,9 @@ QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext() if (!integration) return 0; QWindowsIntegrationPrivate *d = integration->d.data(); + QMutexLocker lock(&d->m_staticContextLock); if (d->m_staticOpenGLContext.isNull()) - d->m_staticOpenGLContext = QSharedPointer(QWindowsStaticOpenGLContext::create()); + d->m_staticOpenGLContext.reset(QWindowsStaticOpenGLContext::create()); return d->m_staticOpenGLContext.data(); } #endif // !QT_NO_OPENGL From 1e971f855546f1b94c7cdf7a31ad64ebe6c3e23d Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Wed, 4 May 2016 16:21:26 -0400 Subject: [PATCH 27/46] Add FreeType libraries for Windows -system-freetype builds Add a "CONFIG += qpa/basicunixfontdatase" to the -system-freetype block so that the FreeType libraries are included in LIBS. Task-number: QTBUG-35767 Change-Id: I81e18e72e068d5ac240cba79bab880e50a033860 Reviewed-by: Oswald Buddenhagen --- src/plugins/platforms/windows/windows.pri | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index eba0593d75..aee6927338 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -124,6 +124,7 @@ contains(QT_CONFIG, freetype) { SOURCES += \ $$PWD/qwindowsfontdatabase_ft.cpp } else:contains(QT_CONFIG, system-freetype) { + CONFIG += qpa/basicunixfontdatabase include($$QT_SOURCE_TREE/src/platformsupport/fontdatabases/basic/basic.pri) HEADERS += \ $$PWD/qwindowsfontdatabase_ft.h From 844ea8beea8d8edb68fea18017cdc57592b2808c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 8 Apr 2016 17:27:14 +0200 Subject: [PATCH 28/46] linuxfb: Support transparency Always clearing to opaque black makes it impossible to create semi-transparent overlays with linuxfb. Instead, behave like other platforms' backingstores: if the target image has an alpha channel, clear to transparent instead and set the correct composition mode. Task-number: QTBUG-52475 Change-Id: I2db4588e0112e200a3aa5eed49f806c37d7ca8b5 Reviewed-by: Louai Al-Khanji --- src/platformsupport/fbconvenience/qfbbackingstore.cpp | 11 ++++++++++- src/platformsupport/fbconvenience/qfbscreen.cpp | 5 ++++- src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp | 7 +++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/platformsupport/fbconvenience/qfbbackingstore.cpp b/src/platformsupport/fbconvenience/qfbbackingstore.cpp index 2800a81507..5eddf71145 100644 --- a/src/platformsupport/fbconvenience/qfbbackingstore.cpp +++ b/src/platformsupport/fbconvenience/qfbbackingstore.cpp @@ -37,6 +37,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -84,9 +85,17 @@ void QFbBackingStore::unlock() mImageMutex.unlock(); } -void QFbBackingStore::beginPaint(const QRegion &) +void QFbBackingStore::beginPaint(const QRegion ®ion) { lock(); + + if (mImage.hasAlphaChannel()) { + QPainter p(&mImage); + p.setCompositionMode(QPainter::CompositionMode_Source); + const QVector rects = region.rects(); + for (QVector::const_iterator it = rects.begin(); it != rects.end(); ++it) + p.fillRect(*it, Qt::transparent); + } } void QFbBackingStore::endPaint() diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp index d00954375d..ad4c62f4a6 100644 --- a/src/platformsupport/fbconvenience/qfbscreen.cpp +++ b/src/platformsupport/fbconvenience/qfbscreen.cpp @@ -233,6 +233,7 @@ QRegion QFbScreen::doRedraw() if (!mCompositePainter) mCompositePainter = new QPainter(mScreenImage); + for (int rectIndex = 0; rectIndex < mRepaintRegion.rectCount(); rectIndex++) { QRegion rectRegion = rects[rectIndex]; @@ -250,7 +251,8 @@ QRegion QFbScreen::doRedraw() foreach (const QRect &rect, intersect.rects()) { bool firstLayer = true; if (layer == -1) { - mCompositePainter->fillRect(rect, Qt::black); + mCompositePainter->setCompositionMode(QPainter::CompositionMode_Source); + mCompositePainter->fillRect(rect, mScreenImage->hasAlphaChannel() ? Qt::transparent : Qt::black); firstLayer = false; layer = mWindowStack.size() - 1; } @@ -283,6 +285,7 @@ QRegion QFbScreen::doRedraw() QRect cursorRect; if (mCursor && (mCursor->isDirty() || mRepaintRegion.intersects(mCursor->lastPainted()))) { + mCompositePainter->setCompositionMode(QPainter::CompositionMode_SourceOver); cursorRect = mCursor->drawCursor(*mCompositePainter); touchedRegion += cursorRect; } diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp index 8c3e73fd80..13e06ef104 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp @@ -405,9 +405,12 @@ QRegion QLinuxFbScreen::doRedraw() if (!mBlitter) mBlitter = new QPainter(&mFbScreenImage); - QVector rects = touched.rects(); - for (int i = 0; i < rects.size(); i++) + const QVector rects = touched.rects(); + mBlitter->setCompositionMode(QPainter::CompositionMode_Source); + + for (int i = 0; i < rects.size(); ++i) mBlitter->drawImage(rects[i], *mScreenImage, rects[i]); + return touched; } From 50723bf3d0d56ba58dbf2343ea890b2d874239e9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 4 Oct 2015 01:00:09 -0400 Subject: [PATCH 29/46] Make sure the QDBusVirtualObject virtuals are called in the right thread Change-Id: I42e7ef1a481840699a8dffff1409e30f191e822f Reviewed-by: Frederik Gladhorn --- tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp index 93d3eacb08..91cae3272a 100644 --- a/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp +++ b/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp @@ -407,6 +407,7 @@ public: VirtualObject() :success(true) {} QString introspect(const QString &path) const { + Q_ASSERT(QThread::currentThread() == thread()); if (path == "/some/path/superNode") return "zitroneneis"; if (path == "/some/path/superNode/foo") @@ -417,6 +418,7 @@ public: } bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) { + Q_ASSERT(QThread::currentThread() == thread()); ++callCount; lastMessage = message; From ab2cf73440e5fbda9e2a3ba15dc1df7895c49679 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Wed, 13 Apr 2016 16:28:57 +0300 Subject: [PATCH 30/46] QXcbDrag: forward mouse release event to initiator window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mouse release event which ends the drag and drop operation must be forwarded to the window where the drag started, and not to the QShapedPixmapWindow, which is not supposed to handle input events. Task-number: QTBUG-52541 Change-Id: I24a7c7b331a06342ac28b420ff9467aa05fe00dd Reviewed-by: Friedemann Kleint Reviewed-by: Błażej Szczygieł Reviewed-by: Dmitry Shachnev Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbdrag.cpp | 14 ++++++++++++++ src/plugins/platforms/xcb/qxcbdrag.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 529f91e1ec..6fa5dfa483 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -50,6 +50,7 @@ #include +#include #include #include #include @@ -170,6 +171,17 @@ QMimeData *QXcbDrag::platformDropData() return dropData; } +bool QXcbDrag::eventFilter(QObject *o, QEvent *e) +{ + /* We are setting a mouse grab on the QShapedPixmapWindow in order not to + * lose the grab when the virtual desktop changes, but + * QBasicDrag::eventFilter() expects the events to be coming from the + * window where the drag was started. */ + if (initiatorWindow && o == shapedPixmapWindow()) + o = initiatorWindow.data(); + return QBasicDrag::eventFilter(o, e); +} + void QXcbDrag::startDrag() { // #fixme enableEventFilter(); @@ -194,6 +206,7 @@ void QXcbDrag::startDrag() setUseCompositing(current_virtual_desktop->compositingActive()); setScreen(current_virtual_desktop->screens().constFirst()->screen()); + initiatorWindow = QGuiApplicationPrivate::currentMouseWindow; QBasicDrag::startDrag(); if (connection()->mouseGrabber() == Q_NULLPTR) shapedPixmapWindow()->setMouseGrabEnabled(true); @@ -202,6 +215,7 @@ void QXcbDrag::startDrag() void QXcbDrag::endDrag() { QBasicDrag::endDrag(); + initiatorWindow.clear(); } static xcb_translate_coordinates_reply_t * diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index c9d257906f..738da1268d 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -69,6 +69,7 @@ public: ~QXcbDrag(); virtual QMimeData *platformDropData() Q_DECL_OVERRIDE; + bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE; void startDrag() Q_DECL_OVERRIDE; void cancel() Q_DECL_OVERRIDE; @@ -106,6 +107,7 @@ private: Qt::DropAction toDropAction(xcb_atom_t atom) const; xcb_atom_t toXdndAction(Qt::DropAction a) const; + QPointer initiatorWindow; QPointer currentWindow; QPoint currentPosition; From d6cbf9efb7c42b10de5fe293589176019faf0373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Thu, 5 May 2016 14:03:56 +0200 Subject: [PATCH 31/46] xcb: Properly unset mousePressWindow() In some cases the mouse release event won't arrive, i.e. when window is minimized on button press. Check for mouse buttons state on mouse move event and properly unset the mousePressWindow to avoid blocking enter/leave events in this case. Amends: c511466d747d99ee76465cfe90ce594fa1f27469 Change-Id: I543a75104f528df1bf644bace13f78a6af017455 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 226507f7a0..429ba8df71 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2351,9 +2351,14 @@ void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, i QPoint local(event_x, event_y); QPoint global(root_x, root_y); - // "mousePressWindow" can be NULL i.e. if a window will be grabbed or umnapped, so set it again here - if (connection()->buttons() != Qt::NoButton && connection()->mousePressWindow() == Q_NULLPTR) + // "mousePressWindow" can be NULL i.e. if a window will be grabbed or unmapped, so set it again here. + // Unset "mousePressWindow" when mouse button isn't pressed - in some cases the release event won't arrive. + const bool isMouseButtonPressed = (connection()->buttons() != Qt::NoButton); + const bool hasMousePressWindow = (connection()->mousePressWindow() != Q_NULLPTR); + if (isMouseButtonPressed && !hasMousePressWindow) connection()->setMousePressWindow(this); + else if (hasMousePressWindow && !isMouseButtonPressed) + connection()->setMousePressWindow(Q_NULLPTR); handleMouseEvent(timestamp, local, global, modifiers, source); } From 7f5e8a5e3475c7f400a47ca821e78feb2e590222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 3 May 2016 11:51:41 +0200 Subject: [PATCH 32/46] OS X: Remove unified toolbar test. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Qt 5 unified toolbar implementation does not move the toolbar to the “non-client” area. This test is no longer relevant. Change-Id: Ia32de2260f8ef400a0dc5acf3e5e3ff59083657a Reviewed-by: Timur Pocheptsov --- tests/auto/widgets/kernel/qwidget/BLACKLIST | 2 - .../widgets/kernel/qwidget/tst_qwidget.cpp | 41 +------------------ 2 files changed, 1 insertion(+), 42 deletions(-) diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index 773f4205af..8fc882112e 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -40,8 +40,6 @@ osx osx [render_systemClip] osx -[childAt_unifiedToolBar] -osx [showMinimizedKeepsFocus] osx-10.10 [moveWindowInShowEvent:1] diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 20bdf00292..7e72007ac0 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -435,7 +435,6 @@ private slots: void movedAndResizedAttributes(); void childAt(); #ifdef Q_OS_OSX - void childAt_unifiedToolBar(); void taskQTBUG_11373(); #endif void taskQTBUG_17333_ResizeInfiniteRecursion(); @@ -9577,49 +9576,10 @@ void tst_QWidget::childAt() } #ifdef Q_OS_OSX -void tst_QWidget::childAt_unifiedToolBar() -{ - QLabel *label = new QLabel(QLatin1String("foo")); - QToolBar *toolBar = new QToolBar; - toolBar->addWidget(new QLabel("dummy")); - toolBar->addWidget(label); - - QMainWindow mainWindow; - mainWindow.addToolBar(toolBar); - mainWindow.show(); - - // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates). - QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint()); - QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint()); - - QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast(toolBar)); - QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast(label)); - - // Enable unified tool bars. - mainWindow.setUnifiedTitleAndToolBarOnMac(true); - QTest::qWait(50); - - // The tool bar is now in the "non-client" area of QMainWindow, i.e. - // outside the mainWindow's rect(), and since mapTo et al. doesn't work - // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8), - // we use mapToGlobal/mapFromGlobal to re-calculate the corners. - QPoint oldToolBarTopLeft = toolBarTopLeft; - toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint())); - QVERIFY2(toolBarTopLeft != oldToolBarTopLeft, - msgComparisonFailed(toolBarTopLeft, "!=", oldToolBarTopLeft)); - QVERIFY2(toolBarTopLeft.y() < 0, - msgComparisonFailed(toolBarTopLeft.y(), "<", 0)); - labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint())); - - QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast(toolBar)); - QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast(label)); -} void tst_QWidget::taskQTBUG_11373() { -#ifdef Q_OS_OSX QSKIP("QTBUG-52974"); -#endif QScopedPointer myWindow(new QMainWindow); QWidget * center = new QWidget(); @@ -9636,6 +9596,7 @@ void tst_QWidget::taskQTBUG_11373() // The drawer should still not be visible, since we haven't shown it. QCOMPARE(drawer->isVisible(), false); } + #endif void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion() From 95b8dfdb6fa834d93646352cf3715d0c71fe29da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 10 May 2016 12:18:24 +0200 Subject: [PATCH 33/46] tst_qwidget: remove sheetOpacity test Sheets are no longer transparent on newer OS X versions. Change-Id: Iaaed5aea9c9b130a5d991acd36717b76c3927cfb Reviewed-by: Timur Pocheptsov --- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 7e72007ac0..183feb4020 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -269,7 +269,6 @@ private slots: void widgetAt(); #ifdef Q_OS_OSX - void sheetOpacity(); void setMask(); #endif void optimizedResizeMove(); @@ -3545,18 +3544,6 @@ void tst_QWidget::testDeletionInEventHandlers() } #ifdef Q_OS_OSX -void tst_QWidget::sheetOpacity() -{ - QSKIP("QTBUG-52974: this test will most probably be deleted - to be investigated."); - QWidget tmpWindow; - QWidget sheet(&tmpWindow, Qt::Sheet); - tmpWindow.show(); - sheet.show(); - QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95% - sheet.setParent(0, Qt::Dialog); - QCOMPARE(int(sheet.windowOpacity() * 255), 255); -} - class MaskedPainter : public QWidget { public: From 7e539002eec2229df21d405acd76dc4f1e1c0ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 3 May 2016 09:25:11 +0200 Subject: [PATCH 34/46] Enable movedAndResizedAttributes test. The test passes on OS X now. Task-number: QTBUG-8941 Change-Id: I7b57dc30ede7c1ed0bcb8bacb458ea56f222d987 Reviewed-by: Timur Pocheptsov --- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 183feb4020..10d32472be 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -9455,10 +9455,6 @@ void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy() void tst_QWidget::movedAndResizedAttributes() { -#if defined (Q_OS_OSX) - QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort); - QVERIFY(false); -#else // Use Qt::Tool as fully decorated windows have a minimum width of 160 on QWidget w(0, Qt::Tool); w.show(); @@ -9504,7 +9500,6 @@ void tst_QWidget::movedAndResizedAttributes() w.resize(100, 100); QVERIFY(w.testAttribute(Qt::WA_Moved)); QVERIFY(w.testAttribute(Qt::WA_Resized)); -#endif } void tst_QWidget::childAt() From 33c5df2887dc738f5c126e2fc406f7aecf63de5f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 3 May 2016 18:38:16 +0200 Subject: [PATCH 35/46] decruft project files the "generated by qt creator" header is not supposed to be checked in. Change-Id: I7626c0bd16f83d81b3facd216a04e7d505942256 Reviewed-by: Joerg Bornemann --- tests/baselineserver/src/baselineserver.pro | 6 ------ tests/manual/qcursor/allcursors/allcursors.pro | 6 ------ tests/manual/qcursor/grab_override/grab_override.pro | 6 ------ tests/manual/qtbug-8933/qtbug-8933.pro | 6 ------ 4 files changed, 24 deletions(-) diff --git a/tests/baselineserver/src/baselineserver.pro b/tests/baselineserver/src/baselineserver.pro index 519cacea9c..a77014c1e6 100644 --- a/tests/baselineserver/src/baselineserver.pro +++ b/tests/baselineserver/src/baselineserver.pro @@ -1,9 +1,3 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2010-08-11T11:51:09 -# -#------------------------------------------------- - QT += core network # gui needed for QImage diff --git a/tests/manual/qcursor/allcursors/allcursors.pro b/tests/manual/qcursor/allcursors/allcursors.pro index c85ef861c2..72bec66940 100644 --- a/tests/manual/qcursor/allcursors/allcursors.pro +++ b/tests/manual/qcursor/allcursors/allcursors.pro @@ -1,9 +1,3 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2009-08-05T17:13:23 -# -#------------------------------------------------- - TARGET = tst_allcursors TEMPLATE = app QT = core gui widgets diff --git a/tests/manual/qcursor/grab_override/grab_override.pro b/tests/manual/qcursor/grab_override/grab_override.pro index d163a726c3..f105fa11e0 100644 --- a/tests/manual/qcursor/grab_override/grab_override.pro +++ b/tests/manual/qcursor/grab_override/grab_override.pro @@ -1,9 +1,3 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2009-08-05T17:13:23 -# -#------------------------------------------------- - TARGET = t_cursors TEMPLATE = app QT = core gui widgets diff --git a/tests/manual/qtbug-8933/qtbug-8933.pro b/tests/manual/qtbug-8933/qtbug-8933.pro index 0d8bfcc797..d92aa3ab66 100644 --- a/tests/manual/qtbug-8933/qtbug-8933.pro +++ b/tests/manual/qtbug-8933/qtbug-8933.pro @@ -1,9 +1,3 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2010-03-16T14:40:16 -# -#------------------------------------------------- - TARGET = qtbug-8933 TEMPLATE = app QT += widgets From dbd81a0b9f884feae797c2a27a59cc9011fb32ff Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 3 May 2016 10:35:03 +0200 Subject: [PATCH 36/46] winrt: Fix potential startup crash Depending on the windowstate passed to QWinRTWindow constructor we might act on the uiElement which has not been created yet. This happened especially in release mode, probably due to timing. Hence delay uiElement changes until we created it in the constructor and can ensure it is valid. Change-Id: I00daa9fcf8542a0535bbcb663a76d85c36e510e2 Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtwindow.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index f5407f8779..75b43205b7 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -108,9 +108,6 @@ QWinRTWindow::QWinRTWindow(QWindow *window) d->surface = EGL_NO_SURFACE; d->display = EGL_NO_DISPLAY; d->screen = static_cast(screen()); - setWindowFlags(window->flags()); - setWindowState(window->windowState()); - setWindowTitle(window->title()); handleContentOrientationChange(window->contentOrientation()); d->surfaceFormat.setAlphaBufferSize(0); @@ -158,6 +155,10 @@ QWinRTWindow::QWinRTWindow(QWindow *window) }); Q_ASSERT_SUCCEEDED(hr); + setWindowFlags(window->flags()); + setWindowState(window->windowState()); + setWindowTitle(window->title()); + setGeometry(window->geometry()); } From 6a84a51611f69f3641ae47bbd7b6bd5266ae88ef Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 6 Apr 2016 10:51:55 -0700 Subject: [PATCH 37/46] QWidgetWindow: Guard reference to own widget ~QWidgetPrivate() may end up calling QWidgetPrivate:: deleteTLSysExtra() which, in turn, calls QWindow::destroy(). This sends an event to the window itself. This reaches QWidgetWindow::event() which will forward the event to the widget. However, the widget has just been deleted since the sequence was initiated by ~QObject(). Task-number: QTBUG-53103 Change-Id: Ib511714a76bbc1e734d6f2800a983eb1459bbf0b Reviewed-by: Marc Mutz Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qwidgetwindow.cpp | 7 +++++-- src/widgets/kernel/qwidgetwindow_p.h | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index b638c6c377..ec2618e501 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -123,7 +123,7 @@ QWidgetWindow::QWidgetWindow(QWidget *widget) && !QApplication::testAttribute(Qt::AA_ForceRasterWidgets)) { setSurfaceType(QSurface::RasterGLSurface); } - connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); + connect(widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); connect(this, SIGNAL(screenChanged(QScreen*)), this, SLOT(handleScreenChange())); } @@ -174,6 +174,9 @@ static inline bool shouldBePropagatedToWidget(QEvent *event) bool QWidgetWindow::event(QEvent *event) { + if (!m_widget) + return QWindow::event(event); + if (m_widget->testAttribute(Qt::WA_DontShowOnScreen)) { // \a event is uninteresting for QWidgetWindow, the event was probably // generated before WA_DontShowOnScreen was set @@ -375,7 +378,7 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event) } else { const QEnterEvent *ee = static_cast(event); QWidget *child = m_widget->childAt(ee->pos()); - QWidget *receiver = child ? child : m_widget; + QWidget *receiver = child ? child : m_widget.data(); QApplicationPrivate::dispatchEnterLeave(receiver, 0, ee->screenPos()); qt_last_mouse_receiver = receiver; } diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h index ca4bac8d86..7fafb01b3d 100644 --- a/src/widgets/kernel/qwidgetwindow_p.h +++ b/src/widgets/kernel/qwidgetwindow_p.h @@ -119,7 +119,7 @@ private: }; QWidget *getFocusWidget(FocusWidgets fw); - QWidget *m_widget; + QPointer m_widget; QPointer m_implicit_mouse_grabber; #ifndef QT_NO_DRAGANDDROP QPointer m_dragTarget; From ce37467acf34edf1380f896a0942b616dc4cbead Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 29 Apr 2016 16:32:42 -0700 Subject: [PATCH 38/46] Acknowledge QWidgetWindow::widget() may be null We guard QWidgetWindow's widget with a QPointer to avoid sending it events during destruction (which may result in undefined behavior, since this originates from ~QObject and we expect the object to behave as a QWidget). Therefore, we need to harden all access to that widget since it can now be null, specially during destruction. As an example, QGestureManager may crash when we delete a top-level widget. The crash stack trace is: 1 QScopedPointer>::data() const 2 QScopedPointer>::pointer qGetPtrHelper>>(QScopedPointer> const&) 3 QWidget::d_func() 4 QGestureManager::filterEvent(QWidget *, QEvent *) <-- the widget ptr is null 5 QGestureManager::filterEvent(QObject *, QEvent *) 6 QApplication::notify(QObject *, QEvent *) 7 QCoreApplication::notifyInternal2(QObject *, QEvent *) 8 QCoreApplication::sendEvent(QObject *, QEvent *) 9 QWindow::destroy() 10 QWidgetPrivate::deleteTLSysExtra() 11 QWidgetPrivate::deleteExtra() 12 QWidgetPrivate::~QWidgetPrivate() 13 QWidgetPrivate::~QWidgetPrivate() 14 QWidgetPrivate::~QWidgetPrivate() 15 QScopedPointerDeleter::cleanup(QObjectData *) 16 QScopedPointer>::~QScopedPointer() 17 QScopedPointer>::~QScopedPointer() 18 QObject::~QObject() 19 QWidget::~QWidget() Task-number: QTBUG-53103 Change-Id: I1bb32648270c4f7791f668b8f0b639ddb4235703 Reviewed-by: Shawn Rutledge Reviewed-by: Marc Mutz --- src/widgets/kernel/qapplication.cpp | 8 ++++---- src/widgets/kernel/qgesturemanager.cpp | 2 +- src/widgets/kernel/qwidgetwindow.cpp | 20 +++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index a459a57482..fcc195f601 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2249,10 +2249,10 @@ void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous) QApplication::setActiveWindow(tlw); // QTBUG-37126, Active X controls may set the focus on native child widgets. if (wnd && tlw && wnd != tlw->windowHandle()) { - if (QWidgetWindow *widgetWindow = qobject_cast(wnd)) { - if (widgetWindow->widget()->inherits("QAxHostWidget")) - widgetWindow->widget()->setFocus(Qt::ActiveWindowFocusReason); - } + if (QWidgetWindow *widgetWindow = qobject_cast(wnd)) + if (QWidget *widget = widgetWindow->widget()) + if (widget->inherits("QAxHostWidget")) + widget->setFocus(Qt::ActiveWindowFocusReason); } } diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 967ef6b40c..89ed6922b5 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -545,7 +545,7 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) // filter method. QWidgetWindow *widgetWindow = qobject_cast(receiver); - if (widgetWindow) + if (widgetWindow && widgetWindow->widget()) return filterEvent(widgetWindow->widget(), event); QGesture *state = qobject_cast(receiver); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index ec2618e501..5290d79d9e 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -87,7 +87,7 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const { Q_Q(const QWidgetWindow); const QWidget *widget = q->widget(); - if (!widget->isWindow() || !widget->hasHeightForWidth()) + if (!widget || !widget->isWindow() || !widget->hasHeightForWidth()) return QRect(); const QSize oldSize = rect.size().toSize(); const QSize newSize = QLayout::closestAcceptableSize(widget, oldSize); @@ -142,16 +142,18 @@ QAccessibleInterface *QWidgetWindow::accessibleRoot() const QObject *QWidgetWindow::focusObject() const { - QWidget *widget = m_widget->focusWidget(); + QWidget *windowWidget = m_widget; + if (!windowWidget) + return Q_NULLPTR; + + QWidget *widget = windowWidget->focusWidget(); if (!widget) - widget = m_widget; + widget = windowWidget; - if (widget) { - QObject *focusObj = QWidgetPrivate::get(widget)->focusObject(); - if (focusObj) - return focusObj; - } + QObject *focusObj = QWidgetPrivate::get(widget)->focusObject(); + if (focusObj) + return focusObj; return widget; } @@ -204,7 +206,7 @@ bool QWidgetWindow::event(QEvent *event) #ifndef QT_NO_ACCESSIBILITY QAccessible::State state; state.active = true; - QAccessibleStateChangeEvent ev(widget(), state); + QAccessibleStateChangeEvent ev(m_widget, state); QAccessible::updateAccessibility(&ev); #endif return false; } From ab3a8443faa36799ab8142e48d25d8ff10f9d0bf Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 29 Apr 2016 18:07:36 +0200 Subject: [PATCH 39/46] QCocoaWindow - do not call resignKeyWindow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QCocoaWindow::setMouseGrabEnabled/setKeyboardGrabEnabled calls resignKeyWindow. According to Apple's docs, we should _never_ call this function (it's done by Cocoa automatically). Calling this function leaves a window in weird state where it can not become key again until you explicitly make another window key first. Task-number: QTBUG-53050 Change-Id: I7a887659df8df11880328ffa2adc07c4a3af63e6 Reviewed-by: Gabriel de Dietrich Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index dd67946a27..c5519995b6 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1135,8 +1135,7 @@ bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) if (grab && ![m_nsWindow isKeyWindow]) [m_nsWindow makeKeyWindow]; - else if (!grab && [m_nsWindow isKeyWindow]) - [m_nsWindow resignKeyWindow]; + return true; } @@ -1147,8 +1146,7 @@ bool QCocoaWindow::setMouseGrabEnabled(bool grab) if (grab && ![m_nsWindow isKeyWindow]) [m_nsWindow makeKeyWindow]; - else if (!grab && [m_nsWindow isKeyWindow]) - [m_nsWindow resignKeyWindow]; + return true; } From acf43c17b647cdbfc3186bb8bf7e183df67a090b Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 1 Mar 2016 15:44:06 +0300 Subject: [PATCH 40/46] QFileSystemModel: create nodes with correct QFileInfos Create parent nodes with the corresponding paths, not with the absolute path of the child node. Otherwise we will get incorrect QFileInfo at least in the following case: QFileSystemModel model; model.setRootPath("/usr/bin"); QModelIndex idx = model.setRootPath("/usr"); qDebug() << model.fileInfo(idx).absoluteFilePath(); Without the fix it prints "/usr/bin". It's a regression triggered by 61cefb2f7a7cb16dfa2732e26d2319017039ef62 (De-inline QFileSystemModel::fileInfo() and implement it efficiently). Change-Id: I3b4e5f5b256711e27ad50824eaa8492dbc096808 Task-number: QTBUG-51586 Reviewed-by: Lars Knoll --- src/widgets/dialogs/qfilesystemmodel.cpp | 21 +++++++++++++------ .../dialogs/qfiledialog/tst_qfiledialog.cpp | 16 ++++++++++++++ .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 21 +++++++++++++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 9bf5a502c3..0e2eee3b47 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -351,6 +351,9 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS ) return const_cast(&root); QModelIndex index = QModelIndex(); // start with "My Computer" + QString elementPath; + QChar separator = QLatin1Char('/'); + QString trailingSeparator; #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) if (absolutePath.startsWith(QLatin1String("//"))) { // UNC path QString host = QLatin1String("\\\\") + pathElements.first(); @@ -358,6 +361,8 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS absolutePath.append(QLatin1Char('/')); if (longPath.endsWith(QLatin1Char('/')) && !absolutePath.endsWith(QLatin1Char('/'))) absolutePath.append(QLatin1Char('/')); + if (absolutePath.endsWith(QLatin1Char('/'))) + trailingSeparator = QLatin1String("\\"); int r = 0; QFileSystemModelPrivate::QFileSystemNode *rootNode = const_cast(&root); if (!root.children.contains(host.toLower())) { @@ -374,11 +379,10 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS r = translateVisibleLocation(rootNode, r); index = q->index(r, 0, QModelIndex()); pathElements.pop_front(); - } else -#endif - -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - { + separator = QLatin1Char('\\'); + elementPath = host; + elementPath.append(separator); + } else { if (!pathElements.at(0).contains(QLatin1Char(':'))) { QString rootPath = QDir(longPath).rootPath(); pathElements.prepend(rootPath); @@ -396,6 +400,11 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS for (int i = 0; i < pathElements.count(); ++i) { QString element = pathElements.at(i); + if (i != 0) + elementPath.append(separator); + elementPath.append(element); + if (i == pathElements.count() - 1) + elementPath.append(trailingSeparator); #ifdef Q_OS_WIN // On Windows, "filename " and "filename" are equivalent and // "filename . " and "filename" are equivalent @@ -427,7 +436,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS if (!alreadyExisted) { // Someone might call ::index("file://cookie/monster/doesn't/like/veggies"), // a path that doesn't exists, I.E. don't blindly create directories. - QFileInfo info(absolutePath); + QFileInfo info(elementPath); if (!info.exists()) return const_cast(&root); QFileSystemModelPrivate *p = const_cast(this); diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index 42e2bd09a5..05f42cf685 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -569,6 +569,22 @@ void tst_QFiledialog::completer() if (expectedFile.startsWith(input, caseSensitivity)) ++expected; } + // The temporary dir may create a node in QFileSystemModel + // which will bypass filters. If the path to the temporary + // dir contains an element which should be a subdirectory + // of x dir, but which is not listed, then take it into + // accont. + if (!tempDir.isNull()) { + QString xPath = x.absolutePath(); + if (!xPath.endsWith(QLatin1Char('/'))) + xPath.append(QLatin1Char('/')); + QString tmpPath = tempDir->path(); + if (tmpPath.startsWith(xPath)) { + QString bypassedDirName = tmpPath.mid(xPath.size()).section(QLatin1Char('/'), 0, 0); + if (!expectedFiles.contains(bypassedDirName)) + ++expected; + } + } } QTRY_COMPARE(cModel->rowCount(), expected); diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 19b1d0e7c8..b27943f071 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -126,6 +126,8 @@ private slots: void doNotUnwatchOnFailedRmdir(); void specialFiles(); + void fileInfo(); + protected: bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList()); @@ -1146,6 +1148,25 @@ void tst_QFileSystemModel::specialFiles() QTRY_VERIFY(!fileListUnderIndex(&model, rootIndex).contains(testFileName)); } +void tst_QFileSystemModel::fileInfo() +{ + QFileSystemModel model; + QModelIndex idx; + + QVERIFY(model.fileInfo(idx).filePath().isEmpty()); + + const QString dirPath = flatDirTestPath; + QDir dir(dirPath); + const QString subdir = QStringLiteral("subdir"); + QVERIFY(dir.mkdir(subdir)); + const QString subdirPath = dir.absoluteFilePath(subdir); + + idx = model.setRootPath(subdirPath); + QCOMPARE(model.fileInfo(idx), QFileInfo(subdirPath)); + idx = model.setRootPath(dirPath); + QCOMPARE(model.fileInfo(idx), QFileInfo(dirPath)); +} + QTEST_MAIN(tst_QFileSystemModel) #include "tst_qfilesystemmodel.moc" From 40a9216e068b804cb9f048ad639a3bb85b185341 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Fri, 29 Apr 2016 11:16:31 +0200 Subject: [PATCH 41/46] Avoid asserting when painting certain degenerate bezier paths It could happen that the stroker would attempt to join empty subpaths, resulting in an invalid path structure that would cause assert later. Task-number: QTBUG-43474 Change-Id: Ia369a31e60c40cdae3900d96f15f3e83c9e78b97 Reviewed-by: Lars Knoll --- src/gui/painting/qstroker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index fc344dc3ac..f6c899a815 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -422,7 +422,7 @@ void QStroker::processCurrentSubpath() bool fwclosed = qt_stroke_side(&fwit, this, false, &fwStartTangent); bool bwclosed = qt_stroke_side(&bwit, this, !fwclosed, &bwStartTangent); - if (!bwclosed) + if (!bwclosed && !fwStartTangent.isNull()) joinPoints(m_elements.at(0).x, m_elements.at(0).y, fwStartTangent, m_capStyle); } From edc4f024104b914c00f7c9354a7805243ce04572 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 11 May 2016 12:40:14 +0200 Subject: [PATCH 42/46] make -R and -D not affect qmake this was meant to be part of d8be8110a, as qmake is obviously also a bootstrapped tool. -I/-L/-F/-l/-fw already had no effect on qmake. Change-Id: I5095742ef5401558cc4432e7a774d0851d417bb0 Reviewed-by: Lars Knoll --- configure | 9 --------- 1 file changed, 9 deletions(-) diff --git a/configure b/configure index 5d02827890..f4555a746b 100755 --- a/configure +++ b/configure @@ -4051,12 +4051,6 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; EXTRA_CXXFLAGS="$EXTRA_CXXFLAGS \$(QMAKE_CXXFLAGS_DEBUG)" fi - if [ -n "$RPATH_FLAGS" ] && [ -n "`getQMakeConf 'QMAKE_(LFLAGS_)?RPATH'`" ]; then - setBootstrapVariable "QMAKE_(LFLAGS_)?RPATH" QMAKE_LFLAGS_RPATH - for rpath in $RPATH_FLAGS; do - EXTRA_LFLAGS="\$(QMAKE_LFLAGS_RPATH)\"$rpath\" $EXTRA_LFLAGS" - done - fi if [ "$BUILD_ON_MSYS" = "yes" ]; then EXTRA_CFLAGS="$EXTRA_CFLAGS -DUNICODE" EXTRA_CXXFLAGS="$EXTRA_CXXFLAGS -DUNICODE" @@ -4104,9 +4098,6 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; \"\$(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp\" \ \"\$(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm\"" fi - if [ '!' -z "$D_FLAGS" ]; then - EXTRA_CFLAGS="$EXTRA_CFLAGS $D_FLAGS" - fi echo >>"$mkfile" adjrelpath=`echo "$relpath" | sed 's/ /\\\\\\\\ /g'` adjoutpath=`echo "$outpath" | sed 's/ /\\\\\\\\ /g'` From c46f74d325892b0f3b3068241535c32ffe6e3a98 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 22 Apr 2016 16:38:32 +0200 Subject: [PATCH 43/46] eglfs: Support dynamic mouse cursor show/hide with DRM HW cursor Task-number: QTBUG-52743 Change-Id: I0bea1451dfe7b049c129b11716d593115e3d8374 Reviewed-by: Louai Al-Khanji --- .../eglfs_kms/qeglfskmscursor.cpp | 59 ++++++++++++++++--- .../eglfs_kms/qeglfskmscursor.h | 30 +++++++++- 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp index 97ea3f1eca..830e270eeb 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 Pier Luigi Fiorini -** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -62,13 +63,13 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen) , m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below , m_bo(Q_NULLPTR) , m_cursorImage(0, 0, 0, 0, 0, 0) - , m_visible(true) + , m_state(CursorPendingVisible) { QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR"); - if (!hideCursorVal.isEmpty()) - m_visible = hideCursorVal.toInt() == 0; - if (!m_visible) + if (!hideCursorVal.isEmpty() && hideCursorVal.toInt()) { + m_state = CursorDisabled; return; + } uint64_t width, height; if ((drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &width) == 0) @@ -85,6 +86,12 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen) initCursorAtlas(); } + m_deviceListener = new QEglFSKmsCursorDeviceListener(this); + connect(QGuiApplicationPrivate::inputDeviceManager(), &QInputDeviceManager::deviceListChanged, + m_deviceListener, &QEglFSKmsCursorDeviceListener::onDeviceListChanged); + if (!m_deviceListener->hasMouse()) + m_state = CursorPendingHidden; + #ifndef QT_NO_CURSOR QCursor cursor(Qt::ArrowCursor); changeCursor(&cursor, 0); @@ -94,6 +101,8 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen) QEglFSKmsCursor::~QEglFSKmsCursor() { + delete m_deviceListener; + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { QEglFSKmsScreen *kmsScreen = static_cast(screen); drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); @@ -106,6 +115,31 @@ QEglFSKmsCursor::~QEglFSKmsCursor() } } +void QEglFSKmsCursor::updateMouseStatus() +{ + const bool wasVisible = m_state == CursorVisible; + const bool visible = m_deviceListener->hasMouse(); + if (visible == wasVisible) + return; + + m_state = visible ? CursorPendingVisible : CursorPendingHidden; + +#ifndef QT_NO_CURSOR + changeCursor(nullptr, m_screen->topLevelAt(pos())); +#endif +} + +bool QEglFSKmsCursorDeviceListener::hasMouse() const +{ + return QGuiApplicationPrivate::inputDeviceManager()->deviceCount(QInputDeviceManager::DeviceTypePointer) > 0; +} + +void QEglFSKmsCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::DeviceType type) +{ + if (type == QInputDeviceManager::DeviceTypePointer) + m_cursor->updateMouseStatus(); +} + void QEglFSKmsCursor::pointerEvent(const QMouseEvent &event) { setPos(event.screenPos().toPoint()); @@ -119,7 +153,15 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window) if (!m_bo) return; - if (!m_visible) + if (m_state == CursorPendingHidden) { + m_state = CursorHidden; + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast(screen); + drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); + } + } + + if (m_state == CursorHidden || m_state == CursorDisabled) return; const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor; @@ -159,6 +201,9 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window) uint32_t handle = gbm_bo_get_handle(m_bo).u32; + if (m_state == CursorPendingVisible) + m_state = CursorVisible; + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { QEglFSKmsScreen *kmsScreen = static_cast(screen); @@ -206,7 +251,7 @@ void QEglFSKmsCursor::initCursorAtlas() drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); } - m_visible = false; + m_state = CursorDisabled; return; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h index 68bc72a03f..f26df91be5 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h @@ -37,12 +37,29 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE class QEglFSKmsScreen; +class QEglFSKmsCursor; + +class QEglFSKmsCursorDeviceListener : public QObject +{ + Q_OBJECT + +public: + QEglFSKmsCursorDeviceListener(QEglFSKmsCursor *cursor) : m_cursor(cursor) { } + bool hasMouse() const; + +public slots: + void onDeviceListChanged(QInputDeviceManager::DeviceType type); + +private: + QEglFSKmsCursor *m_cursor; +}; class QEglFSKmsCursor : public QPlatformCursor { @@ -60,15 +77,26 @@ public: QPoint pos() const Q_DECL_OVERRIDE; void setPos(const QPoint &pos) Q_DECL_OVERRIDE; + void updateMouseStatus(); + private: void initCursorAtlas(); + enum CursorState { + CursorDisabled, + CursorPendingHidden, + CursorHidden, + CursorPendingVisible, + CursorVisible + }; + QEglFSKmsScreen *m_screen; QSize m_cursorSize; gbm_bo *m_bo; QPoint m_pos; QPlatformCursorImage m_cursorImage; - bool m_visible; + CursorState m_state; + QEglFSKmsCursorDeviceListener *m_deviceListener; // cursor atlas information struct CursorAtlas { From 36578d41f3fe43a3cd3c37d8bdaaf3f9a50eca92 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 10 May 2016 17:01:47 -0700 Subject: [PATCH 44/46] Remove wrong doc note for QPlatformBackingStore::flush() This is no longer true on at least Cocoa, Windows and xcb. Change-Id: I214caae46a8707ab7c89138646219140079e919a Reviewed-by: Jake Petroules --- src/gui/painting/qplatformbackingstore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 33d5e76e52..defdcfb4ad 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -226,7 +226,8 @@ void QPlatformTextureList::clear() Flushes the given \a region from the specified \a window onto the screen. - Note that the \a offset parameter is currently unused. + The \a offset parameter is relative to the origin of the backing + store image. */ #ifndef QT_NO_OPENGL From 37a983cd98afb3ae1e7295a5e2fd0929542865f9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 10 May 2016 16:24:08 +0200 Subject: [PATCH 45/46] Dirview example: Add option for DontUseCustomDirectoryIcons. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables people to toy around with the option and check what impact it has. Change-Id: I8b49c31211cc48721b3326eea48b4e74967b1a92 Reviewed-by: Sérgio Martins --- examples/widgets/itemviews/dirview/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/widgets/itemviews/dirview/main.cpp b/examples/widgets/itemviews/dirview/main.cpp index abca413325..2f030643ca 100644 --- a/examples/widgets/itemviews/dirview/main.cpp +++ b/examples/widgets/itemviews/dirview/main.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,8 @@ int main(int argc, char *argv[]) parser.setApplicationDescription("Qt Dir View Example"); parser.addHelpOption(); parser.addVersionOption(); + QCommandLineOption dontUseCustomDirectoryIconsOption("c", "Set QFileIconProvider::DontUseCustomDirectoryIcons"); + parser.addOption(dontUseCustomDirectoryIconsOption); parser.addPositionalArgument("directory", "The directory to start in."); parser.process(app); const QString rootPath = parser.positionalArguments().isEmpty() @@ -61,6 +64,8 @@ int main(int argc, char *argv[]) QFileSystemModel model; model.setRootPath(""); + if (parser.isSet(dontUseCustomDirectoryIconsOption)) + model.iconProvider()->setOptions(QFileIconProvider::DontUseCustomDirectoryIcons); QTreeView tree; tree.setModel(&model); if (!rootPath.isEmpty()) { From 6bcd27b957a5ffcfe7665b0979679510e3b2ae3d Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 10 May 2016 14:35:20 +0200 Subject: [PATCH 46/46] Document how to save an application using QUndoStack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ic61374d5b6ce395dfe8d0b30813ea437b5e16e9d Task-number: QTBUG-52497 Reviewed-by: Topi Reiniö --- src/widgets/util/qundostack.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index 5bcfa57b37..bd41fb60c1 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -623,6 +623,8 @@ void QUndoStack::push(QUndoCommand *cmd) Marks the stack as clean and emits cleanChanged() if the stack was not already clean. + This is typically called when a document is saved, for example. + Whenever the stack returns to this state through the use of undo/redo commands, it emits the signal cleanChanged(). This signal is also emitted when the stack leaves the clean state.