From 717ff946391233e7e4a99b8042494512ca3957d7 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 26 Feb 2016 10:15:20 -0800 Subject: QMenuBar: Acknowledge AA_DontUseNativeMenuBar Change-Id: I756f4181d66ef6e79ab7b7be8a23a10171a9f30c Task-number: QTBUG-28960 Reviewed-by: Timur Pocheptsov --- src/widgets/widgets/qmenubar.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/widgets') diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 2e48607f82..cca0853a8f 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -690,7 +690,8 @@ void QMenuBarPrivate::init() q->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); q->setAttribute(Qt::WA_CustomWhatsThis); - platformMenuBar = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar(); + if (!QApplication::instance()->testAttribute(Qt::AA_DontUseNativeMenuBar)) + platformMenuBar = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar(); if (platformMenuBar) q->hide(); -- cgit v1.2.3 From 8b94ceaff8e67827302a1190ad828cb90cf3b977 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 26 Feb 2016 10:15:43 -0800 Subject: QMacStyle and QCocoaTheme: Fix selected item color for non-native menubar Change-Id: I3b55e9ce896383338cf6ed768d912ca1835b7742 Task-number: QTBUG-28960 Reviewed-by: Timur Pocheptsov --- src/widgets/styles/qmacstyle_mac.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index ac23512f1d..4f688f6f28 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -4608,7 +4608,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter HIRect menuRect = qt_hirectForQRect(mi->menuRect); HIRect itemRect = qt_hirectForQRect(mi->rect); - if ((opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken)){ + const bool selected = (opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken); + if (selected) { // Draw a selected menu item background: HIThemeMenuItemDrawInfo mdi; mdi.version = qt_mac_hitheme_version; @@ -4636,7 +4637,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip | Qt::TextSingleLine, mi->palette, mi->state & State_Enabled, - mi->text, QPalette::ButtonText); + mi->text, selected ? QPalette::HighlightedText : QPalette::ButtonText); } } break; -- cgit v1.2.3 From afe3c30759d1bf9f52278d8dc40f85a93a1d963b Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 26 Feb 2016 13:56:55 -0800 Subject: Don't create accessible interface for QWidgets being destroyed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I975ee556913707e8595b2a89f1bba4299187bcfb Reviewed-by: Wayne Arnold Reviewed-by: Jan Arve Sæther --- src/widgets/accessible/qaccessiblewidgetfactory.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/widgets') diff --git a/src/widgets/accessible/qaccessiblewidgetfactory.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp index 4fa7c89482..261bc69000 100644 --- a/src/widgets/accessible/qaccessiblewidgetfactory.cpp +++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp @@ -33,6 +33,7 @@ #include "qaccessiblewidgets_p.h" #include "qaccessiblemenu_p.h" +#include "private/qwidget_p.h" #include "simplewidgets_p.h" #include "rangecontrols_p.h" #include "complexwidgets_p.h" @@ -53,7 +54,15 @@ QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *obje QAccessibleInterface *iface = 0; if (!object || !object->isWidgetType()) return iface; + QWidget *widget = static_cast(object); + // QWidget emits destroyed() from its destructor instead of letting the QObject + // destructor do it, which means the QWidget is unregistered from the accessibillity + // cache. But QWidget destruction also emits enter and leave events, which may end + // up here, so we have to ensure that we don't fill the cache with an entry of + // a widget that is going away. + if (QWidgetPrivate::get(widget)->data.in_destructor) + return iface; if (false) { #ifndef QT_NO_LINEEDIT -- cgit v1.2.3 From 4f577051676ad8ff161d481030f016d0c6bb324f Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 5 Mar 2016 00:34:01 +0100 Subject: Fix GCC 6 -Wunused-functions warnings GCC 6 is able to identify member functions that are unused. Remove them. Change-Id: Ic77548164b38a1cd3c957d2c57a5bccb979bc02e Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/dialogs/qcolordialog.cpp | 15 --------------- src/widgets/widgets/qcalendarwidget.cpp | 6 ------ 2 files changed, 21 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 468bffe49e..9a8bfc552d 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -190,7 +190,6 @@ public: QSize sizeHint() const Q_DECL_OVERRIDE; virtual void setCellBrush(int row, int col, const QBrush &); - QBrush cellBrush(int row, int col); inline int cellWidth() const { return cellw; } @@ -459,20 +458,6 @@ void QWellArray::setCellBrush(int row, int col, const QBrush &b) d->brush[row*numCols()+col] = b; } -/* - Returns the brush set for the cell at \a row, \a column. If no brush is - set, Qt::NoBrush is returned. -*/ - -QBrush QWellArray::cellBrush(int row, int col) -{ - if (d && row >= 0 && row < numRows() && col >= 0 && col < numCols()) - return d->brush[row*numCols()+col]; - return Qt::NoBrush; -} - - - /*!\reimp */ diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp index 48b224fe13..89cde851e5 100644 --- a/src/widgets/widgets/qcalendarwidget.cpp +++ b/src/widgets/widgets/qcalendarwidget.cpp @@ -654,7 +654,6 @@ public: int dateEditAcceptDelay() const; void setDateEditAcceptDelay(int delay); - QDate date() const; void setDate(const QDate &date); bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE; @@ -690,11 +689,6 @@ void QCalendarTextNavigator::setWidget(QWidget *widget) m_widget = widget; } -QDate QCalendarTextNavigator::date() const -{ - return m_date; -} - void QCalendarTextNavigator::setDate(const QDate &date) { m_date = date; -- cgit v1.2.3 From d5fde514106f5479f9c929c8a165aced4a1b2c84 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 1 Mar 2016 13:17:13 +0100 Subject: QWheelEvent: make NoScrollPhase opt-in The fix for QTBUG-50199 involves adding an undocumented enum value which can be returned from QWheelEvent::phase(). This will be quite unexpected for applications that use it, which work fine with 5.6.0 and then start receiving this new phase value in 5.6.1. So it should not happen by default. Set the env variable QT_ENABLE_MOUSE_WHEEL_TRACKING to enable this functionality. In 5.7 it will be default behavior. But in 5.6 the default behavior is as it was before: if you use a conventional mouse wheel, the phase stays at ScrollUpdate continuously. [ChangeLog][QtCore] QWheelEvent::phase() returns 0 rather than Qt::ScrollUpdate when the wheel event comes from an actual non-emulated mouse wheel and the environment variable QT_ENABLE_MOUSE_WHEEL_TRACKING is set. In Qt 5.6, this is required to enable the fix for QTBUG-50199. Change-Id: Ieb2152ff767df24c42730d201235d1225aaec832 Reviewed-by: Gabriel de Dietrich Reviewed-by: Shawn Rutledge Reviewed-by: Alex Blasche --- src/widgets/kernel/qapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 7c5a0da0c1..50e5ccf938 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3341,7 +3341,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) res = d->notify_helper(w, &we); eventAccepted = we.isAccepted(); if (res && eventAccepted) { - if (spontaneous && phase != Qt::NoScrollPhase) + if (spontaneous && phase != Qt::NoScrollPhase && QGuiApplicationPrivate::scrollNoPhaseAllowed) QApplicationPrivate::wheel_widget = w; break; } -- cgit v1.2.3 From 559152d911ceff8af5020355b35d7a1da100398c Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 18 Sep 2014 13:13:21 +0400 Subject: Make an implicit grab on TouchBegin for a widget subscribed to a gesture A receiver of TouchUpdate and TouchEnd events is determined either as a widget which has an implicit grab for the touch point or as a visible widget if there are no implicit grabs. The events are sent if the receiver has accepted TouchBegin event or if it is subscribed to a gesture. Before sending the events to the widget they are delivered to the gesture manager. Thus, in order to detect gestures for the widget, it must own an implicit grab or be a visible widget. It can happen that the parent widget is subscribed to a gesture, but doesn't accept TouchBegin event, as in the case of QScrollArea. Then it will not get an implicit grab and gesture detection will be impossible. Activate an implicit grab for such widgets. Also don't send TouchUpdate and TouchEnd to them, because it's against the documentation. Task-number: QTBUG-43277 Change-Id: Id767583991def6d76c48ad15eb39af822cad115d Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qapplication.cpp | 52 +++++++++++++++++++++++++++++++------ src/widgets/kernel/qapplication_p.h | 1 + 2 files changed, 45 insertions(+), 8 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 50e5ccf938..f7d4139ed8 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3548,6 +3548,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, e, localPos); } +#ifndef QT_NO_GESTURES + QPointer gesturePendingWidget; +#endif + while (widget) { // first, try to deliver the touch event acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); @@ -3565,14 +3569,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e) touchEvent->spont = false; if (res && eventAccepted) { // the first widget to accept the TouchBegin gets an implicit grab. - for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { - const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i); - d->activeTouchPoints[QGuiApplicationPrivate::ActiveTouchPointsKey(touchEvent->device(), touchPoint.id())].target = widget; - } - break; - } else if (p.isNull() || widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) { + d->activateImplicitTouchGrab(widget, touchEvent); break; } +#ifndef QT_NO_GESTURES + if (gesturePendingWidget.isNull() && widget && QGestureManager::gesturePending(widget)) + gesturePendingWidget = widget; +#endif + if (p.isNull() || widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) + break; + QPoint offset = widget->pos(); widget = widget->parentWidget(); touchEvent->setTarget(widget); @@ -3586,9 +3592,27 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } } +#ifndef QT_NO_GESTURES + if (!eventAccepted && !gesturePendingWidget.isNull()) { + // the first widget subscribed to a gesture gets an implicit grab + d->activateImplicitTouchGrab(gesturePendingWidget, touchEvent); + } +#endif + touchEvent->setAccepted(eventAccepted); break; } + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + QWidget *widget = static_cast(receiver); + // We may get here if the widget is subscribed to a gesture, + // but has not accepted TouchBegin. Propagate touch events + // only if TouchBegin has been accepted. + if (widget && widget->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent)) + res = d->notify_helper(widget, e); + break; + } case QEvent::RequestSoftwareInputPanel: inputMethod()->show(); break; @@ -4328,6 +4352,17 @@ QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device, return static_cast(closestTarget); } +void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent) +{ + if (touchEvent->type() != QEvent::TouchBegin) + return; + + for (int i = 0, tc = touchEvent->touchPoints().count(); i < tc; ++i) { + const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i); + activeTouchPoints[QGuiApplicationPrivate::ActiveTouchPointsKey(touchEvent->device(), touchPoint.id())].target = widget; + } +} + bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, QTouchDevice *device, const QList &touchPoints, @@ -4458,10 +4493,11 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, || QGestureManager::gesturePending(widget) #endif ) { - if (touchEvent.type() == QEvent::TouchEnd) - widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false); if (QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted()) accepted = true; + // widget can be deleted on TouchEnd + if (touchEvent.type() == QEvent::TouchEnd && !widget.isNull()) + widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false); } break; } diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 4cce2d84e8..cb158011f0 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -282,6 +282,7 @@ public: QWidget *findClosestTouchPointTarget(QTouchDevice *device, const QTouchEvent::TouchPoint &touchPoint); void appendTouchPoint(const QTouchEvent::TouchPoint &touchPoint); void removeTouchPoint(int touchPointId); + void activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchBeginEvent); static bool translateRawTouchEvent(QWidget *widget, QTouchDevice *device, const QList &touchPoints, -- cgit v1.2.3 From a90485dd01bd6c067bf977cb30604032352da6be Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 20 Jan 2016 10:46:00 +0100 Subject: Make use of defaultDropAction in QListView icon mode Before this patch, using setDefaultDropAction on QListView in icon mode would not have any effect. Now the drag behaves properly. The default action is set to CopyAction rather than IgnoreAction to keep the current behavior and avoid breaking user code. [ChangeLog][QtWidgets][QListWidget] Fixed a bug that caused the default drop action to be ignored when using icon mode. Task-number: QTBUG-15741 Change-Id: I49654cde382af344ffc4594699303c928e27e05d Reviewed-by: Marc Mutz --- src/widgets/itemviews/qlistview.cpp | 7 ++++++- src/widgets/itemviews/qlistview_p.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index a17d89e735..18ea19c8b9 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1978,6 +1978,11 @@ int QCommonListViewBase::horizontalScrollToValue(const int /*index*/, QListView: /* * ListMode ListView Implementation */ +QListModeViewBase::QListModeViewBase(QListView *q, QListViewPrivate *d) + : QCommonListViewBase(q, d) +{ + dd->defaultDropAction = Qt::CopyAction; +} #ifndef QT_NO_DRAGANDDROP QAbstractItemView::DropIndicatorPosition QListModeViewBase::position(const QPoint &pos, const QRect &rect, const QModelIndex &index) const @@ -2744,7 +2749,7 @@ bool QIconModeViewBase::filterStartDrag(Qt::DropActions supportedActions) drag->setMimeData(dd->model->mimeData(indexes)); drag->setPixmap(pixmap); drag->setHotSpot(dd->pressedPosition - rect.topLeft()); - Qt::DropAction action = drag->exec(supportedActions, Qt::CopyAction); + Qt::DropAction action = drag->exec(supportedActions, dd->defaultDropAction); draggedItems.clear(); if (action == Qt::MoveAction) dd->clearOrRemove(); diff --git a/src/widgets/itemviews/qlistview_p.h b/src/widgets/itemviews/qlistview_p.h index 62fa45e640..d1ea6fe328 100644 --- a/src/widgets/itemviews/qlistview_p.h +++ b/src/widgets/itemviews/qlistview_p.h @@ -193,7 +193,7 @@ public: class QListModeViewBase : public QCommonListViewBase { public: - QListModeViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d) {} + QListModeViewBase(QListView *q, QListViewPrivate *d); QVector flowPositions; QVector segmentPositions; -- cgit v1.2.3 From 65ec933f91dd9ac95679c24c830533953e384991 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 5 Mar 2016 11:09:52 +0100 Subject: QCompleter: QMatchData: init all fields in default ctor Found by UBSan: src/widgets/util/qcompleter_p.h:130:8: runtime error: load of value 249, which is not a valid value for type 'bool' Change-Id: I0529e54e17a6f4d6add91786a2d5687f2d043531 Reviewed-by: Milian Wolff --- src/widgets/util/qcompleter_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets') diff --git a/src/widgets/util/qcompleter_p.h b/src/widgets/util/qcompleter_p.h index b100f24f9b..afcdfe7aa2 100644 --- a/src/widgets/util/qcompleter_p.h +++ b/src/widgets/util/qcompleter_p.h @@ -122,7 +122,7 @@ private: }; struct QMatchData { - QMatchData() : exactMatchIndex(-1) { } + QMatchData() : exactMatchIndex(-1), partial(false) { } QMatchData(const QIndexMapper& indices, int em, bool p) : indices(indices), exactMatchIndex(em), partial(p) { } QIndexMapper indices; -- cgit v1.2.3 From a28364bc1c7144b9c5c383cc5d18d62a68076a38 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 12 Feb 2016 16:03:42 +0100 Subject: consistently put {qt,qml}_{module,plugin} at the end of project files this fixes static builds by ensuring that all dependencies are exported. Task-number: QTBUG-51071 Change-Id: Icbce502dcbcb4d4b4d922c42679f44e2cc930bf3 Reviewed-by: Joerg Bornemann --- src/widgets/accessible/widgets.pro | 10 ++++------ src/widgets/widgets.pro | 9 ++++----- 2 files changed, 8 insertions(+), 11 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/accessible/widgets.pro b/src/widgets/accessible/widgets.pro index c6af6d3f71..da8607c637 100644 --- a/src/widgets/accessible/widgets.pro +++ b/src/widgets/accessible/widgets.pro @@ -1,10 +1,5 @@ TARGET = qtaccessiblewidgets -PLUGIN_TYPE = accessible -PLUGIN_EXTENDS = widgets -PLUGIN_CLASS_NAME = AccessibleFactory -load(qt_plugin) - QT += core-private gui-private widgets-private QTDIR_build:REQUIRES += "contains(QT_CONFIG, accessibility)" @@ -24,4 +19,7 @@ HEADERS += qaccessiblewidgets.h \ qaccessiblemenu.h \ itemviews.h - +PLUGIN_TYPE = accessible +PLUGIN_EXTENDS = widgets +PLUGIN_CLASS_NAME = AccessibleFactory +load(qt_plugin) diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro index ceb6f96f7c..b609e4c434 100644 --- a/src/widgets/widgets.pro +++ b/src/widgets/widgets.pro @@ -8,13 +8,8 @@ DEFINES += QT_NO_USING_NAMESPACE win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000 irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused -MODULE_PLUGIN_TYPES += \ - styles - QMAKE_DOCS = $$PWD/doc/qtwidgets.qdocconf -load(qt_module) - #platforms mac:include(kernel/mac.pri) win32:include(kernel/win.pri) @@ -45,3 +40,7 @@ QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtWidgets.dynlist testcocoon { load(testcocoon) } + +MODULE_PLUGIN_TYPES += \ + styles +load(qt_module) -- cgit v1.2.3 From f2bd0d119200d5b66069725563f7f12952e66da8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 3 Mar 2016 15:17:01 +0100 Subject: Clean up WINVER, _WIN32_WINNT macros for MinGW. Define WINVER, _WIN32_WINNT as 0x501 (Windows XP) in qt_windows.h. Remove definitions of the same/lower versions and unneeded definitions in other places. Remove definition for Borland compiler. Task-number: QTBUG-51673 Change-Id: I2a344a7f7cf78b2afbf45dcdf8bf2a19b93f0a07 Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- src/widgets/dialogs/qwizard_win.cpp | 12 ------------ src/widgets/styles/qwindowsxpstyle_p_p.h | 12 ------------ src/widgets/util/qsystemtrayicon_win.cpp | 7 ------- 3 files changed, 31 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp index a4b37f360b..b210cb904d 100644 --- a/src/widgets/dialogs/qwizard_win.cpp +++ b/src/widgets/dialogs/qwizard_win.cpp @@ -47,18 +47,6 @@ #include #include -// Note, these tests are duplicates in qwindowsxpstyle_p.h. -#ifdef Q_CC_GNU -# include -# if (__W32API_MAJOR_VERSION >= 3 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION >= 5)) -# ifdef _WIN32_WINNT -# undef _WIN32_WINNT -# endif -# define _WIN32_WINNT 0x0501 -# include -# endif -#endif - #include Q_DECLARE_METATYPE(QMargins) diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 5a0abc1d78..e1e1369850 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -50,18 +50,6 @@ #include #include -// Note, these tests are duplicated in qwizard_win.cpp. -#ifdef Q_CC_GNU -# include -# if (__W32API_MAJOR_VERSION >= 3 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION >= 5)) -# ifdef _WIN32_WINNT -# undef _WIN32_WINNT -# endif -# define _WIN32_WINNT 0x0501 -# include -# endif -#endif - #include #if WINVER >= 0x0600 diff --git a/src/widgets/util/qsystemtrayicon_win.cpp b/src/widgets/util/qsystemtrayicon_win.cpp index f1b86ba2df..7e0212a233 100644 --- a/src/widgets/util/qsystemtrayicon_win.cpp +++ b/src/widgets/util/qsystemtrayicon_win.cpp @@ -34,13 +34,6 @@ #include "qsystemtrayicon_p.h" #ifndef QT_NO_SYSTEMTRAYICON -#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600 -# undef _WIN32_WINNT -#endif -#if !defined(_WIN32_WINNT) -# define _WIN32_WINNT 0x0600 -#endif - #if defined(_WIN32_IE) && _WIN32_IE < 0x0600 # undef _WIN32_IE #endif -- cgit v1.2.3 From 1b441c3941efc56f9b0ead35a4501056a74a77e1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 7 Mar 2016 20:26:14 +0100 Subject: Q*Application: fix UB caused by accessing QGuiApplication from QCoreApplication ctor As reported by ubsan: src/gui/kernel/qplatformintegration.cpp:463:10: runtime error: downcast of address 0x7ffdc2942490 which does not point to an object of type 'QGuiApplication' 0x7ffdc2942490: note: object is of type 'QCoreApplication' src/gui/kernel/qplatformintegration.cpp:466:14: runtime error: downcast of address 0x7ffdc2942490 which does not point to an object of type 'QGuiApplication' 0x7ffdc2942490: note: object is of type 'QCoreApplication' src/gui/kernel/qplatformintegration.cpp:466:43: runtime error: member call on address 0x7ffdc2942490 which does not point to an object of type 'QGuiApplication' 0x7ffdc2942490: note: object is of type 'QCoreApplication' to name just a few which are reported when running gui and widget auto-tests; there're definitely more where these came from. This is caused by QCoreApplication::init() being called from the QCoreApplication ctor, calling virtual functions on Q*AppPrivate, which happen to attempt, in this case, to emit QGuiApp signals. At that point in time, the QGuiApplication ctor has not entered the constructor body, ergo the object is still a QCoreApplication, and calling the signal, as a member function on the derived class, invokes UB. Fix by cleaning up the wild mix of initialization functions used in this hierarchy. The cleanup restores the 1. Q*ApplicationPrivate::Q*ApplicationPrivate() 2. Q*ApplicationPrivate::init(), calling each base class' init() as the first thing two-stage construction pattern commonly used elsewhere in Qt to make sure that the public class' object is fully constructed by the time each level's Private::init() is called. Change-Id: I290402b3232315d7ed687c97e740bfbdbd3ecd1a Reviewed-by: Lars Knoll --- src/widgets/kernel/qapplication.cpp | 9 +++++++-- src/widgets/kernel/qapplication_p.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index f7d4139ed8..b7de0d7a7e 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -562,13 +562,18 @@ QApplication::QApplication(int &argc, char **argv) QApplication::QApplication(int &argc, char **argv, int _internal) #endif : QGuiApplication(*new QApplicationPrivate(argc, argv, _internal)) -{ Q_D(QApplication); d->construct(); } +{ + Q_D(QApplication); + d->init(); +} /*! \internal */ -void QApplicationPrivate::construct() +void QApplicationPrivate::init() { + QGuiApplicationPrivate::init(); + initResources(); qt_is_gui_used = (application_type != QApplicationPrivate::Tty); diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index cb158011f0..832d37a329 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -150,7 +150,7 @@ public: bool notify_helper(QObject *receiver, QEvent * e); - void construct( + void init( #ifdef Q_DEAD_CODE_FROM_QT4_X11 Display *dpy = 0, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 #endif -- cgit v1.2.3 From 3856099d9a6c9cd90747d530819df8c99198fa54 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 9 Mar 2016 11:09:18 +0100 Subject: QGestureManager: fix UB in filterEvent() The code infers from the presence of an address in a QHash that the address belongs to a QGesture. So far that is fine enough. But in order to perform the lookup, it static_cast<>s the QObject* argument to a QGesture* for the QHash:: contains() call. Even though the pointer is not dereferenced, the cast is UB. Says UBSan: qgesturemanager.cpp:558:73: runtime error: downcast of address 0x2ab83364f3a0 which does not point to an object of type 'QGesture' 0x2ab83364f3a0: note: object is of type 'QDBusConnectionManager' which is a particularly hideous error message because of the constantly-changing completely-unrelated actual type in the second line of the message: 52 QDBusConnectionManager 19 QSocketNotifier 14 QFusionStyle 13 QAction 6 QApplication 3 QGraphicsWidget 1 Window 1 TestRunnable 1 RectWidget 1 QTimer 1 QSingleShotTimer 1 QOffscreenSurface 1 QGraphicsProxyWidget 1 QDefaultAnimationDriver 1 QDBusPendingCallWatcherHelper This error is also _very_ common, triggered 116 times in a single run of make -C tests/auto check. Fix by using qobject_cast first and then doing the lookup only when the cast succeeded. Depending on the performance of qobject_cast<>, this may actually perform better, too. Change-Id: I884ec7d885711acc3c1d004ce93c628268d8fc18 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/kernel/qgesturemanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index fb2914d53a..967ef6b40c 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -548,9 +548,9 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) if (widgetWindow) return filterEvent(widgetWindow->widget(), event); - if (!m_gestureToRecognizer.contains(static_cast(receiver))) + QGesture *state = qobject_cast(receiver); + if (!state || !m_gestureToRecognizer.contains(state)) return false; - QGesture *state = static_cast(receiver); QMultiMap contexts; contexts.insert(state, state->gestureType()); return filterEventThroughContexts(contexts, event); -- cgit v1.2.3 From 85a57f7a2e85ac61bb65e66b003cb21f58d5a5b7 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 3 Mar 2016 13:51:19 -0800 Subject: Wheel event widget: Harden logic an extra bit This is quite an unlikely scenario, but not impossible. It could be that the wheel widget is destroyed during an update phase event. In that case, wheel_widget would be a dangling pointer for any subsequent wheel event. We protect against this with a QPointer. However, that would mean that if the next wheel event were to be an end phase event, that event would be lost. So we go through the usual code path, except that we won't set wheel_widget in the case of an end phase event. Change-Id: I59a912b845dcc249e1edc60b4dc28bf308d807d9 Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qapplication.cpp | 76 +++++++++++++++++++++++++------------ src/widgets/kernel/qapplication_p.h | 2 +- 2 files changed, 53 insertions(+), 25 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index b7de0d7a7e..b34380dbc3 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -417,7 +417,7 @@ QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard inpu QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus #ifndef QT_NO_WHEELEVENT int QApplicationPrivate::wheel_scroll_lines; // number of lines to scroll -QWidget *QApplicationPrivate::wheel_widget = Q_NULLPTR; +QPointer QApplicationPrivate::wheel_widget; #endif bool qt_in_tab_key_event = false; int qt_antialiasing_threshold = -1; @@ -3326,9 +3326,32 @@ bool QApplication::notify(QObject *receiver, QEvent *e) const bool spontaneous = wheel->spontaneous(); const Qt::ScrollPhase phase = wheel->phase(); - if (phase == Qt::NoScrollPhase || phase == Qt::ScrollBegin - || (phase == Qt::ScrollUpdate && !QApplicationPrivate::wheel_widget)) { - + // Ideally, we should lock on a widget when it starts receiving wheel + // events. This avoids other widgets to start receiving those events + // as the mouse cursor hovers them. However, given the way common + // wheeled mice work, there's no certain way of connecting different + // wheel events as a stream. This results in the NoScrollPhase case, + // where we just send the event from the original receiver and up its + // hierarchy until the event gets accepted. + // + // In the case of more evolved input devices, like Apple's trackpad or + // Magic Mouse, we receive the scroll phase information. This helps us + // connect wheel events as a stream and therefore makes it easier to + // lock on the widget onto which the scrolling was initiated. + // + // We assume that, when supported, the phase cycle follows the pattern: + // + // ScrollBegin (ScrollUpdate* ScrollEnd)+ + // + // This means that we can have scrolling sequences (starting with ScrollBegin) + // or partial sequences (after a ScrollEnd and starting with ScrollUpdate). + // If wheel_widget is null because it was deleted, we also take the same + // code path as an initial sequence. + if (phase == Qt::NoScrollPhase || phase == Qt::ScrollBegin || !QApplicationPrivate::wheel_widget) { + + // A system-generated ScrollBegin event starts a new user scrolling + // sequence, so we reset wheel_widget in case no one accepts the event + // or if we didn't get (or missed) a ScrollEnd previously. if (spontaneous && phase == Qt::ScrollBegin) QApplicationPrivate::wheel_widget = Q_NULLPTR; @@ -3346,7 +3369,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e) res = d->notify_helper(w, &we); eventAccepted = we.isAccepted(); if (res && eventAccepted) { - if (spontaneous && phase != Qt::NoScrollPhase && QGuiApplicationPrivate::scrollNoPhaseAllowed) + // A new scrolling sequence or partial sequence starts and w has accepted + // the event. Therefore, we can set wheel_widget, but only if it's not + // the end of a sequence. + if (spontaneous && (phase == Qt::ScrollBegin || phase == Qt::ScrollUpdate) && QGuiApplicationPrivate::scrollNoPhaseAllowed) QApplicationPrivate::wheel_widget = w; break; } @@ -3357,25 +3383,27 @@ bool QApplication::notify(QObject *receiver, QEvent *e) w = w->parentWidget(); } wheel->setAccepted(eventAccepted); - } else if (QApplicationPrivate::wheel_widget) { - if (!spontaneous) { - // wheel_widget may forward the wheel event to a delegate widget, - // either directly or indirectly (e.g. QAbstractScrollArea will - // forward to its QScrollBars through viewportEvent()). In that - // case, the event will not be spontaneous but synthesized, so - // we can send it straigth to the receiver. - d->notify_helper(w, wheel); - } else { - const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); - QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), - wheel->modifiers(), wheel->phase(), wheel->source()); - we.spont = true; - we.ignore(); - d->notify_helper(QApplicationPrivate::wheel_widget, &we); - wheel->setAccepted(we.isAccepted()); - if (phase == Qt::ScrollEnd) - QApplicationPrivate::wheel_widget = Q_NULLPTR; - } + } else if (!spontaneous) { + // wheel_widget may forward the wheel event to a delegate widget, + // either directly or indirectly (e.g. QAbstractScrollArea will + // forward to its QScrollBars through viewportEvent()). In that + // case, the event will not be spontaneous but synthesized, so + // we can send it straight to the receiver. + d->notify_helper(w, wheel); + } else { + // The phase is either ScrollUpdate or ScrollEnd, and wheel_widget + // is set. Since it accepted the wheel event previously, we continue + // sending those events until we get a ScrollEnd, which signifies + // the end of the natural scrolling sequence. + const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); + QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), + wheel->modifiers(), wheel->phase(), wheel->source()); + we.spont = true; + we.ignore(); + d->notify_helper(QApplicationPrivate::wheel_widget, &we); + wheel->setAccepted(we.isAccepted()); + if (phase == Qt::ScrollEnd) + QApplicationPrivate::wheel_widget = Q_NULLPTR; } } break; diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 832d37a329..4b3cf773dc 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -202,7 +202,7 @@ public: static QWidget *active_window; #ifndef QT_NO_WHEELEVENT static int wheel_scroll_lines; - static QWidget *wheel_widget; + static QPointer wheel_widget; #endif static int enabledAnimations; // Combination of QPlatformTheme::UiEffect -- cgit v1.2.3