summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-10-17 10:19:31 +0200
committerLiang Qi <liang.qi@qt.io>2017-10-17 10:34:24 +0200
commitd0a0a3c0418a0fdd2ed84b2a5f7e6565537715c6 (patch)
treed6aeb4d51caf30ccf23eadb806a09295cbf679cd /src/widgets/kernel
parent9f405f98a4247cd263b9c5d35659a4ba89e282de (diff)
parentac35f9c44c0fb3b2f40ae5585c497200b2ba743d (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.cpp37
-rw-r--r--src/widgets/kernel/qwidget.cpp127
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp6
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp8
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp6
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 &region, 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() {