diff options
author | Liang Qi <liang.qi@qt.io> | 2017-10-17 10:19:31 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-10-17 10:34:24 +0200 |
commit | d0a0a3c0418a0fdd2ed84b2a5f7e6565537715c6 (patch) | |
tree | d6aeb4d51caf30ccf23eadb806a09295cbf679cd /src/widgets/kernel | |
parent | 9f405f98a4247cd263b9c5d35659a4ba89e282de (diff) | |
parent | ac35f9c44c0fb3b2f40ae5585c497200b2ba743d (diff) |
Merge remote-tracking branch 'origin/5.10' into dev
Conflicts:
examples/network/fortuneclient/client.cpp
examples/network/fortuneserver/server.cpp
src/platformsupport/platformcompositor/qopenglcompositorbackingstore_p.h
src/plugins/platforms/cocoa/qcocoabackingstore.h
src/plugins/platforms/cocoa/qcocoaintegration.h
src/plugins/platforms/cocoa/qcocoascreen.h
src/plugins/platforms/ios/qiosbackingstore.h
src/plugins/sqldrivers/oci/qsql_oci.cpp
src/widgets/kernel/qwidgetwindow.cpp
Change-Id: Ia6dd2c52d4a691b671cf9a2ffca70deccece8f10
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r-- | src/widgets/kernel/qgesturemanager.cpp | 37 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 127 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetbackingstore.cpp | 6 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 8 | ||||
-rw-r--r-- | src/widgets/kernel/qwindowcontainer.cpp | 6 |
5 files changed, 107 insertions, 77 deletions
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index fca36c7472..5bf66d68e3 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -244,6 +244,36 @@ QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recogni return state; } +static bool logIgnoredEvent(QEvent::Type t) +{ + bool result = false; + switch (t) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchCancel: + case QEvent::TouchEnd: + case QEvent::TabletEnterProximity: + case QEvent::TabletLeaveProximity: + case QEvent::TabletMove: + case QEvent::TabletPress: + case QEvent::TabletRelease: + case QEvent::GraphicsSceneMouseDoubleClick: + case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseRelease: + case QEvent::GraphicsSceneMouseMove: + result = true; + break; + default: + break; + + } + return result; +} + bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, Qt::GestureType> &contexts, QEvent *event) @@ -289,10 +319,13 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, qCDebug(lcGestureManager) << "QGestureManager:Recognizer: not gesture: " << state << event; notGestures << state; } else if (recognizerState == QGestureRecognizer::Ignore) { - qCDebug(lcGestureManager) << "QGestureManager:Recognizer: ignored the event: " << state << event; + if (logIgnoredEvent(event->type())) + qCDebug(lcGestureManager) << "QGestureManager:Recognizer: ignored the event: " << state << event; } else { - qCDebug(lcGestureManager) << "QGestureManager:Recognizer: hm, lets assume the recognizer" + if (logIgnoredEvent(event->type())) { + qCDebug(lcGestureManager) << "QGestureManager:Recognizer: hm, lets assume the recognizer" << "ignored the event: " << state << event; + } } if (resultHint & QGestureRecognizer::ConsumeEventHint) { qCDebug(lcGestureManager) << "QGestureManager: we were asked to consume the event: " diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 0aa5f57e98..6a633fb575 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1876,39 +1876,15 @@ static void deleteBackingStore(QWidgetPrivate *d) { QTLWExtra *topData = d->topData(); - // The context must be current when destroying the backing store as it may attempt to - // release resources like textures and shader programs. The window may not be suitable - // anymore as there will often not be a platform window underneath at this stage. Fall - // back to a QOffscreenSurface in this case. - QScopedPointer<QOffscreenSurface> tempSurface; -#ifndef QT_NO_OPENGL - if (d->textureChildSeen && topData->shareContext) { - if (topData->window->handle()) { - topData->shareContext->makeCurrent(topData->window); - } else { - tempSurface.reset(new QOffscreenSurface); - tempSurface->setFormat(topData->shareContext->format()); - tempSurface->create(); - topData->shareContext->makeCurrent(tempSurface.data()); - } - } -#endif - delete topData->backingStore; topData->backingStore = 0; - -#ifndef QT_NO_OPENGL - if (d->textureChildSeen && topData->shareContext) - topData->shareContext->doneCurrent(); -#endif } void QWidgetPrivate::deleteTLSysExtra() { if (extra && extra->topextra) { //the qplatformbackingstore may hold a reference to the window, so the backingstore - //needs to be deleted first. If the backingstore holds GL resources, we need to - // make the context current here. This is taken care of by deleteBackingStore(). + //needs to be deleted first. extra->topextra->backingStoreTracker.destroy(); deleteBackingStore(this); @@ -5912,7 +5888,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * pixmapOffset -= effectRect.topLeft(); - const qreal dpr = context->painter->device()->devicePixelRatio(); + const qreal dpr = context->painter->device()->devicePixelRatioF(); QPixmap pixmap(effectRect.size() * dpr); pixmap.setDevicePixelRatio(dpr); @@ -6945,6 +6921,9 @@ bool QWidget::isActiveWindow() const /*! Puts the \a second widget after the \a first widget in the focus order. + It effectively removes the \a second widget from its focus chain and + inserts it after the \a first widget. + Note that since the tab order of the \a second widget is changed, you should order a chain like this: @@ -6957,11 +6936,19 @@ bool QWidget::isActiveWindow() const If \a first or \a second has a focus proxy, setTabOrder() correctly substitutes the proxy. + \note Since Qt 5.10: A widget that has a child as focus proxy is understood as + a compound widget. When setting a tab order between one or two compound widgets, the + local tab order inside each will be preserved. This means that if both widgets are + compound widgets, the resulting tab order will be from the last child inside + \a first, to the first child inside \a second. + \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets} */ void QWidget::setTabOrder(QWidget* first, QWidget *second) { - if (!first || !second || first->focusPolicy() == Qt::NoFocus || second->focusPolicy() == Qt::NoFocus) + if (!first || !second || first == second + || first->focusPolicy() == Qt::NoFocus + || second->focusPolicy() == Qt::NoFocus) return; if (Q_UNLIKELY(first->window() != second->window())) { @@ -6969,54 +6956,56 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second) return; } - QWidget *fp = first->focusProxy(); - if (fp) { - // If first is redirected, set first to the last child of first - // that can take keyboard focus so that second is inserted after - // that last child, and the focus order within first is (more - // likely to be) preserved. - QList<QWidget *> l = first->findChildren<QWidget *>(); - for (int i = l.size()-1; i >= 0; --i) { - QWidget * next = l.at(i); - if (next->window() == fp->window()) { - fp = next; - if (fp->focusPolicy() != Qt::NoFocus) - break; - } - } - first = fp; - } + auto determineLastFocusChild = [](QWidget *target, QWidget *&lastFocusChild) + { + // Since we need to repeat the same logic for both 'first' and 'second', we add a function that + // determines the last focus child for a widget, taking proxies and compound widgets into account. + // If the target is not a compound widget (it doesn't have a focus proxy that points to a child), + // 'lastFocusChild' will be set to the target itself. + lastFocusChild = target; + + QWidget *focusProxy = target->d_func()->deepestFocusProxy(); + if (!focusProxy || !target->isAncestorOf(focusProxy)) + return; - if (fp == second) - return; + lastFocusChild = focusProxy; - if (QWidget *sp = second->focusProxy()) - second = sp; + for (QWidget *focusNext = lastFocusChild->d_func()->focus_next; + focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window(); + focusNext = focusNext->d_func()->focus_next) { + if (focusNext->focusPolicy() != Qt::NoFocus) + lastFocusChild = focusNext; + } + }; -// QWidget *fp = first->d_func()->focus_prev; - QWidget *fn = first->d_func()->focus_next; + QWidget *lastFocusChildOfFirst, *lastFocusChildOfSecond; + determineLastFocusChild(first, lastFocusChildOfFirst); + determineLastFocusChild(second, lastFocusChildOfSecond); - if (fn == second || first == second) + // If the tab order is already correct, exit early + if (lastFocusChildOfFirst->d_func()->focus_next == second) return; - QWidget *sp = second->d_func()->focus_prev; - QWidget *sn = second->d_func()->focus_next; - - fn->d_func()->focus_prev = second; - first->d_func()->focus_next = second; - - second->d_func()->focus_next = fn; - second->d_func()->focus_prev = first; - - sp->d_func()->focus_next = sn; - sn->d_func()->focus_prev = sp; - - - Q_ASSERT(first->d_func()->focus_next->d_func()->focus_prev == first); - Q_ASSERT(first->d_func()->focus_prev->d_func()->focus_next == first); - - Q_ASSERT(second->d_func()->focus_next->d_func()->focus_prev == second); - Q_ASSERT(second->d_func()->focus_prev->d_func()->focus_next == second); + // Note that we need to handle two different sections in the tab chain; The section + // that 'first' belongs to (firstSection), where we are about to insert 'second', and + // the section that 'second' used be a part of (secondSection). When we pull 'second' + // out of the second section and insert it into the first, we also need to ensure + // that we leave the second section in a connected state. + QWidget *firstChainOldSecond = lastFocusChildOfFirst->d_func()->focus_next; + QWidget *secondChainNewFirst = second->d_func()->focus_prev; + QWidget *secondChainNewSecond = lastFocusChildOfSecond->d_func()->focus_next; + + // Insert 'second' after 'first' + lastFocusChildOfFirst->d_func()->focus_next = second; + second->d_func()->focus_prev = lastFocusChildOfFirst; + + // The widget that used to be 'second' in the first section, should now become 'third' + lastFocusChildOfSecond->d_func()->focus_next = firstChainOldSecond; + firstChainOldSecond->d_func()->focus_prev = lastFocusChildOfSecond; + + // Repair the second section after we pulled 'second' out of it + secondChainNewFirst->d_func()->focus_next = secondChainNewSecond; + secondChainNewSecond->d_func()->focus_prev = secondChainNewFirst; } /*!\internal diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index b851a5c0af..3b093283cd 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -143,10 +143,8 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBack // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends // to rely on translucency, in order to decide if it should clear to transparent or opaque. const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); - // Use the tlw's context, not widget's. The difference is important with native child - // widgets where tlw != widget. - backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, widgetTextures, - tlw->d_func()->shareContext(), translucentBackground); + backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, + widgetTextures, translucentBackground); widget->window()->d_func()->sendComposeStatus(widget->window(), true); } else #endif diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index e5027e35df..80ed39bf76 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -96,6 +96,7 @@ public: } QRectF closestAcceptableGeometry(const QRectF &rect) const override; + QOpenGLContext *shareContext() const override; }; QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const @@ -127,6 +128,13 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const return result; } +QOpenGLContext *QWidgetWindowPrivate::shareContext() const +{ + Q_Q(const QWidgetWindow); + const QWidgetPrivate *widgetPrivate = QWidgetPrivate::get(q->widget()); + return widgetPrivate->shareContext(); +} + QWidgetWindow::QWidgetWindow(QWidget *widget) : QWindow(*new QWidgetWindowPrivate(), 0) , m_widget(widget) diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index d2ad7a466e..d388327687 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -89,7 +89,7 @@ public: void updateUsesNativeWidgets() { - if (usesNativeWidgets || window->parent() == 0) + if (window->parent() == 0) return; Q_Q(QWindowContainer); if (q->internalWinId()) { @@ -97,6 +97,7 @@ public: usesNativeWidgets = true; return; } + bool nativeWidgetSet = false; QWidget *p = q->parentWidget(); while (p) { if (false @@ -108,11 +109,12 @@ public: #endif ) { q->winId(); - usesNativeWidgets = true; + nativeWidgetSet = true; break; } p = p->parentWidget(); } + usesNativeWidgets = nativeWidgetSet; } void markParentChain() { |