From ac4bab991b0b258853611dd2b5662dc111fa6311 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 22 Oct 2014 10:30:46 +0200 Subject: QSwipeGestureRecognizer: Prevent cancel in startup-phase. Replace the boolean 'started' member by an enumeration which indicates the startup phase. While in that phase, do not cancel when pressed points are detected for fewer than 3 touch points. Task-number: QTBUG-15768 Change-Id: Ic57b19e3002392fb632f551f615d80ada9831d34 Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qgesture_p.h | 10 ++++++++-- src/widgets/kernel/qstandardgestures.cpp | 23 +++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h index 8668145d8a..183a2eba0f 100644 --- a/src/widgets/kernel/qgesture_p.h +++ b/src/widgets/kernel/qgesture_p.h @@ -134,11 +134,17 @@ class QSwipeGesturePrivate : public QGesturePrivate Q_DECLARE_PUBLIC(QSwipeGesture) public: + enum State { + NoGesture, + Started, + ThreePointsReached + }; + QSwipeGesturePrivate() : horizontalDirection(QSwipeGesture::NoDirection), verticalDirection(QSwipeGesture::NoDirection), swipeAngle(0), - started(false), velocityValue(0) + state(NoGesture), velocityValue(0) { } @@ -150,7 +156,7 @@ public: qreal swipeAngle; QPoint lastPositions[3]; - bool started; + State state; qreal velocityValue; QElapsedTimer time; }; diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp index 0822c04033..9e3cb473e5 100644 --- a/src/widgets/kernel/qstandardgestures.cpp +++ b/src/widgets/kernel/qstandardgestures.cpp @@ -283,7 +283,7 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, case QEvent::TouchBegin: { d->velocityValue = 1; d->time.start(); - d->started = true; + d->state = QSwipeGesturePrivate::Started; result = QGestureRecognizer::MayBeGesture; break; } @@ -297,9 +297,10 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, } case QEvent::TouchUpdate: { const QTouchEvent *ev = static_cast(event); - if (!d->started) + if (d->state == QSwipeGesturePrivate::NoGesture) result = QGestureRecognizer::CancelGesture; else if (ev->touchPoints().size() == 3) { + d->state = QSwipeGesturePrivate::ThreePointsReached; QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); QTouchEvent::TouchPoint p3 = ev->touchPoints().at(2); @@ -354,12 +355,18 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, } else if (ev->touchPoints().size() > 3) { result = QGestureRecognizer::CancelGesture; } else { // less than 3 touch points - if (d->started && (ev->touchPointStates() & Qt::TouchPointPressed)) - result = QGestureRecognizer::CancelGesture; - else if (d->started) - result = QGestureRecognizer::Ignore; - else + switch (d->state) { + case QSwipeGesturePrivate::NoGesture: result = QGestureRecognizer::MayBeGesture; + break; + case QSwipeGesturePrivate::Started: + result = QGestureRecognizer::Ignore; + break; + case QSwipeGesturePrivate::ThreePointsReached: + result = (ev->touchPointStates() & Qt::TouchPointPressed) + ? QGestureRecognizer::CancelGesture : QGestureRecognizer::Ignore; + break; + } } break; } @@ -378,7 +385,7 @@ void QSwipeGestureRecognizer::reset(QGesture *state) d->swipeAngle = 0; d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint(); - d->started = false; + d->state = QSwipeGesturePrivate::NoGesture; d->velocityValue = 0; d->time.invalidate(); -- cgit v1.2.3 From 6080db8c6d345cf4ad573215828246e86f9dc41b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 14 Oct 2014 16:58:01 +0200 Subject: Check geometry correctly when replaying popup mouse events. Task-number: QTBUG-41869 Task-number: QTBUG-39313 Change-Id: I2b59f5db6f0ae4007b1a3b58a79eed958e662272 Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qwidgetwindow.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index d40fc84d77..1cd042f99d 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -433,14 +433,19 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) QWindow *win = w->windowHandle(); if (!win) win = w->nativeParentWidget()->windowHandle(); - if (win && win->geometry().contains(event->globalPos())) { - // Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec() - const QPoint localPos = win->mapFromGlobal(event->globalPos()); - QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers()); - QCoreApplicationPrivate::setEventSpontaneous(e, true); - QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event)); - e->setTimestamp(event->timestamp()); - QCoreApplication::postEvent(win, e); + if (win) { + const QRect globalGeometry = win->isTopLevel() + ? win->geometry() + : QRect(win->mapToGlobal(QPoint(0, 0)), win->size()); + if (globalGeometry.contains(event->globalPos())) { + // Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec() + const QPoint localPos = win->mapFromGlobal(event->globalPos()); + QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers()); + QCoreApplicationPrivate::setEventSpontaneous(e, true); + QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event)); + e->setTimestamp(event->timestamp()); + QCoreApplication::postEvent(win, e); + } } } } -- cgit v1.2.3 From a0bdbc144299be3b77ceafdd28b23bf0e041a657 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 27 Oct 2014 17:04:37 +0100 Subject: Fix QWidget::scroll during painting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling scroll during painting fails in cases where the scroll is attempted accelerated. This is easily fixed by not using accelerated scrolling during painting. Task-number: QTBUG-41615 Change-Id: I38d2428d5679c242f13d53793a3dc3b8e01b538f Reviewed-by: Jørgen Lind --- src/widgets/kernel/qwidgetbackingstore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 00052c868f..9f014aa4fe 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -869,7 +869,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) QRect scrollRect = rect & clipRect(); bool overlapped = false; - bool accelerateScroll = accelEnv && isOpaque + bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent) && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft()))); if (!accelerateScroll) { -- cgit v1.2.3 From 3d5fb54eda2330d76c11a10c39fc70541eddf4a5 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 29 Oct 2014 08:44:40 +0100 Subject: Cocoa: Handle Qt::WA_MacAlwaysShowToolWindow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forward the flag to QWindow by setting the _q_macAlwaysShowToolWindowproperty on the window in QWidgetPrivate::create_sys(). Test for the property when creating the window. Task-number: QTBUG-29816 Done-with: Morten Sørvig Change-Id: Id810dda98d02deb0902192cce1783d8b16b04d04 Reviewed-by: Morten Johan Sørvig --- src/widgets/kernel/qwidget.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 7533cacbdc..cc262fa3e2 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1405,6 +1405,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if (q->testAttribute(Qt::WA_ShowWithoutActivating)) win->setProperty("_q_showWithoutActivating", QVariant(true)); + if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow)) + win->setProperty("_q_macAlwaysShowToolWindow", QVariant::fromValue(QVariant(true))); win->setFlags(data.window_flags); fixPosIncludesFrame(); if (q->testAttribute(Qt::WA_Moved) -- cgit v1.2.3 From dce13e4b7b0d6cf04879fc3b1f2a241579296e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Wed, 22 Oct 2014 13:29:52 +0200 Subject: Fix too many resizes and move events for native widgets When the QWidgetWindow receives a resize or move event, it should check with the widget if its crect already has this geometry. if not then send the resize or move event Ideally events should be sent whenever the QWidgetWindow receives them. QTBUG-42383 is created for this problem Task-number: QTBUG-29937 Task-number: QTBUG-38768 Task-number: QTBUG-30744 Change-Id: I1e9a5d25de29a98885edece927ba14d7a763eb01 Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qwidget.cpp | 5 +--- src/widgets/kernel/qwidgetwindow.cpp | 53 ++++++++++++++++++++++++++---------- src/widgets/kernel/qwidgetwindow_p.h | 4 ++- 3 files changed, 42 insertions(+), 20 deletions(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index cc262fa3e2..315d615d89 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -7155,10 +7155,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) } } - // generate a move event for QWidgets without window handles. QWidgets with native - // window handles already receive a move event from - // QGuiApplicationPrivate::processGeometryChangeEvent. - if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) { + if (isMove) { QMoveEvent e(q->pos(), oldPos); QApplication::sendEvent(q, &e); } diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 1cd042f99d..e455b772fb 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -543,14 +543,36 @@ void QWidgetWindow::handleKeyEvent(QKeyEvent *event) QGuiApplication::sendSpontaneousEvent(receiver, event); } -void QWidgetWindow::updateGeometry() +bool QWidgetWindow::updateSize() { + bool changed = false; if (m_widget->testAttribute(Qt::WA_OutsideWSRange)) - return; + return changed; + if (m_widget->data->crect.size() != geometry().size()) { + changed = true; + m_widget->data->crect.setSize(geometry().size()); + } - const QMargins margins = frameMargins(); + updateMargins(); + return changed; +} + +bool QWidgetWindow::updatePos() +{ + bool changed = false; + if (m_widget->testAttribute(Qt::WA_OutsideWSRange)) + return changed; + if (m_widget->data->crect.topLeft() != geometry().topLeft()) { + changed = true; + m_widget->data->crect.moveTopLeft(geometry().topLeft()); + } + updateMargins(); + return changed; +} - m_widget->data->crect = geometry(); +void QWidgetWindow::updateMargins() +{ + const QMargins margins = frameMargins(); QTLWExtra *te = m_widget->d_func()->topData(); te->posIncludesFrame= false; te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom()); @@ -609,24 +631,25 @@ void QWidgetWindow::updateNormalGeometry() void QWidgetWindow::handleMoveEvent(QMoveEvent *event) { - updateGeometry(); - QGuiApplication::sendSpontaneousEvent(m_widget, event); + if (updatePos()) + QGuiApplication::sendSpontaneousEvent(m_widget, event); } void QWidgetWindow::handleResizeEvent(QResizeEvent *event) { QSize oldSize = m_widget->data->crect.size(); - updateGeometry(); - QGuiApplication::sendSpontaneousEvent(m_widget, event); + if (updateSize()) { + QGuiApplication::sendSpontaneousEvent(m_widget, event); - if (m_widget->d_func()->paintOnScreen()) { - QRegion updateRegion(geometry()); - if (m_widget->testAttribute(Qt::WA_StaticContents)) - updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); - m_widget->d_func()->syncBackingStore(updateRegion); - } else { - m_widget->d_func()->syncBackingStore(); + if (m_widget->d_func()->paintOnScreen()) { + QRegion updateRegion(geometry()); + if (m_widget->testAttribute(Qt::WA_StaticContents)) + updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); + m_widget->d_func()->syncBackingStore(updateRegion); + } else { + m_widget->d_func()->syncBackingStore(); + } } } diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h index 7f12ae8e20..0632a5c364 100644 --- a/src/widgets/kernel/qwidgetwindow_p.h +++ b/src/widgets/kernel/qwidgetwindow_p.h @@ -108,7 +108,9 @@ private slots: private: void repaintWindow(); - void updateGeometry(); + bool updateSize(); + bool updatePos(); + void updateMargins(); void updateNormalGeometry(); enum FocusWidgets { -- cgit v1.2.3 From ea8d4869b722f0eca2b7bbbdd77ac7e3a13ccd10 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 7 Nov 2014 09:32:11 +0100 Subject: a widget's window is transient for its parent's top-level window When a widget's parent's window is not a top-level window, it should find the top-level window before calling setTransientParent, to avoid a warning (since a71e285133087714034f3c84a758980c85b3801e). Task-number: QTBUG-42464 Change-Id: I732691b0d40aba226470332426775d1bd4381009 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qwidget.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 315d615d89..78eabf3c4c 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -10511,8 +10511,9 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) QWidget *parentWithWindow = newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0; if (parentWithWindow) { - if (f & Qt::Window) { - q->windowHandle()->setTransientParent(parentWithWindow->windowHandle()); + QWidget *topLevel = parentWithWindow->window(); + if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) { + q->windowHandle()->setTransientParent(topLevel->windowHandle()); q->windowHandle()->setParent(0); } else { q->windowHandle()->setTransientParent(0); -- cgit v1.2.3 From 63f5b1a7fccca3cf8d7082eeffec31a15cc36de7 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 5 Nov 2014 14:51:06 +0100 Subject: send touch update when more points begin after single touch is ignored Otherwise, a widget can't detect pinches if the points don't start simultaneously unless it sets WA_TouchPadAcceptSingleTouchEvents. The use case is for a widget that doesn't actually want the single touch events, but only when there are two or more touchpoints. Task-number: QTBUG-42389 Change-Id: I5269d9acb93a0001c4fde02b1f7b9e0dfcc0032f Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qapplication.cpp | 12 ++++++++++-- src/widgets/kernel/qapplication_p.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 8f6c5d748c..269fe452c1 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -4230,8 +4230,9 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) return true; } -void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent) +bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent) { + bool containsPress = false; for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i]; @@ -4244,7 +4245,11 @@ void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven touchPoint.d->rect = rect; touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta; + + if (touchPoint.state() == Qt::TouchPointPressed) + containsPress = true; } + return containsPress; } void QApplicationPrivate::initializeMultitouch() @@ -4391,11 +4396,14 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, QApplication::keyboardModifiers(), it.value().first, it.value().second); - updateTouchPointsForWidget(widget, &touchEvent); + bool containsPress = updateTouchPointsForWidget(widget, &touchEvent); touchEvent.setTimestamp(timestamp); touchEvent.setWindow(window->windowHandle()); touchEvent.setTarget(widget); + if (containsPress) + widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent); + switch (touchEvent.type()) { case QEvent::TouchBegin: { diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 156bf34194..7d97235c66 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -275,7 +275,7 @@ public: QPixmap *ignore_cursor; #endif - static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); + static bool updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); void initializeMultitouch(); void initializeMultitouch_sys(); void cleanupMultitouch(); -- cgit v1.2.3 From 2fb3941198f43b653cb53f53b59830c9b9856835 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 30 Oct 2014 14:43:51 +0100 Subject: QPanGestureRecognizer: Make the number of touch points a parameter. Prepare for determining the suitable number of touch points from the device type. For now, 2 points are used as before, which can be overridden by setting the environment variable QT_PAN_TOUCHPOINTS. Add member variable to QPanGesturePrivate which is set on gesture creation and later used for comparison. Task-number: QTBUG-40461 Change-Id: I6d9e35ca752375bc6a54435482ca0925195b8142 Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qgesture_p.h | 3 ++- src/widgets/kernel/qgesturemanager.cpp | 20 +++++++++++++++++++- src/widgets/kernel/qstandardgestures.cpp | 32 +++++++++++++++----------------- src/widgets/kernel/qstandardgestures_p.h | 5 ++++- 4 files changed, 40 insertions(+), 20 deletions(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h index 183a2eba0f..26d9ede59d 100644 --- a/src/widgets/kernel/qgesture_p.h +++ b/src/widgets/kernel/qgesture_p.h @@ -80,7 +80,7 @@ class QPanGesturePrivate : public QGesturePrivate public: QPanGesturePrivate() - : acceleration(0), xVelocity(0), yVelocity(0) + : acceleration(0), xVelocity(0), yVelocity(0), pointCount(2) { } @@ -95,6 +95,7 @@ public: qreal acceleration; qreal xVelocity; qreal yVelocity; + int pointCount; // ### fixme Qt 5.5: Add accessor to QPanGesture. }; class QPinchGesturePrivate : public QGesturePrivate diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 739e6b1870..c9af3062d3 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -63,6 +63,24 @@ QT_BEGIN_NAMESPACE +static inline int panTouchPoints() +{ + // Override by environment variable for testing. + static const char panTouchPointVariable[] = "QT_PAN_TOUCHPOINTS"; + if (qEnvironmentVariableIsSet(panTouchPointVariable)) { + bool ok; + const int result = qgetenv(panTouchPointVariable).toInt(&ok); + if (ok && result >= 1) + return result; + qWarning() << "Ignoring invalid value of " << panTouchPointVariable; + } + // Pan should use 1 finger on a touch screen and 2 fingers on touch pads etc. + // where 1 finger movements are used for mouse event synthetization. For now, + // default to 2 until all classes inheriting QScrollArea are fixed to handle it + // correctly. + return 2; +} + QGestureManager::QGestureManager(QObject *parent) : QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture) { @@ -73,7 +91,7 @@ QGestureManager::QGestureManager(QObject *parent) registerGestureRecognizer(new QMacPinchGestureRecognizer); registerGestureRecognizer(new QMacPanGestureRecognizer); #else - registerGestureRecognizer(new QPanGestureRecognizer); + registerGestureRecognizer(new QPanGestureRecognizer(panTouchPoints())); registerGestureRecognizer(new QPinchGestureRecognizer); registerGestureRecognizer(new QSwipeGestureRecognizer); registerGestureRecognizer(new QTapGestureRecognizer); diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp index 9e3cb473e5..6656903e70 100644 --- a/src/widgets/kernel/qstandardgestures.cpp +++ b/src/widgets/kernel/qstandardgestures.cpp @@ -44,10 +44,6 @@ QT_BEGIN_NAMESPACE -QPanGestureRecognizer::QPanGestureRecognizer() -{ -} - QGesture *QPanGestureRecognizer::create(QObject *target) { if (target && target->isWidgetType()) { @@ -62,6 +58,15 @@ QGesture *QPanGestureRecognizer::create(QObject *target) return new QPanGesture; } +static QPointF panOffset(const QList &touchPoints, int maxCount) +{ + QPointF result; + const int count = qMin(touchPoints.size(), maxCount); + for (int p = 0; p < count; ++p) + result += touchPoints.at(p).pos() - touchPoints.at(p).startPos(); + return result / qreal(count); +} + QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event) @@ -76,18 +81,15 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, result = QGestureRecognizer::MayBeGesture; QTouchEvent::TouchPoint p = ev->touchPoints().at(0); d->lastOffset = d->offset = QPointF(); + d->pointCount = m_pointCount; break; } case QEvent::TouchEnd: { if (q->state() != Qt::NoGesture) { const QTouchEvent *ev = static_cast(event); - if (ev->touchPoints().size() == 2) { - QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); - QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + if (ev->touchPoints().size() == d->pointCount) { d->lastOffset = d->offset; - d->offset = - QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(), - p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2; + d->offset = panOffset(ev->touchPoints(), d->pointCount); } result = QGestureRecognizer::FinishGesture; } else { @@ -97,16 +99,12 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, } case QEvent::TouchUpdate: { const QTouchEvent *ev = static_cast(event); - if (ev->touchPoints().size() >= 2) { - QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); - QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + if (ev->touchPoints().size() >= d->pointCount) { d->lastOffset = d->offset; - d->offset = - QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(), - p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2; + d->offset = panOffset(ev->touchPoints(), d->pointCount); if (d->offset.x() > 10 || d->offset.y() > 10 || d->offset.x() < -10 || d->offset.y() < -10) { - q->setHotSpot(p1.startScreenPos()); + q->setHotSpot(ev->touchPoints().first().startScreenPos()); result = QGestureRecognizer::TriggerGesture; } else { result = QGestureRecognizer::MayBeGesture; diff --git a/src/widgets/kernel/qstandardgestures_p.h b/src/widgets/kernel/qstandardgestures_p.h index aeabd9cc7e..15ba31f26a 100644 --- a/src/widgets/kernel/qstandardgestures_p.h +++ b/src/widgets/kernel/qstandardgestures_p.h @@ -55,11 +55,14 @@ QT_BEGIN_NAMESPACE class QPanGestureRecognizer : public QGestureRecognizer { public: - QPanGestureRecognizer(); + explicit QPanGestureRecognizer(int pointCount = 2) : m_pointCount(pointCount) {} QGesture *create(QObject *target); QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); void reset(QGesture *state); + +private: + const int m_pointCount; }; class QPinchGestureRecognizer : public QGestureRecognizer -- cgit v1.2.3 From b00d4475aafa31fef808c4b5839383b827273ddd Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Nov 2014 10:13:14 +0100 Subject: Fix broken resource cleanup in QOpenGLWidget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The context has to be made current. Otherwise we may fail to clean up or, what's worse, we may delete FBOs and textures in some random context. The latter was visible with ANGLE in the qopenglwidget example. When having two QOpenGLWidget instances, the context for the second happened to be the current one when destroying the first. This is now avoided by making sure the correct context is current when deleting the FBOs. Task-number: QTBUG-42696 Change-Id: I8c1eed7c13a869968cc67141e585d02c6bc6f279 Reviewed-by: Friedemann Kleint Reviewed-by: Jørgen Lind --- src/widgets/kernel/qopenglwidget.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 8a4e0c8ffd..eee4aa546c 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -578,12 +578,22 @@ GLuint QOpenGLWidgetPrivate::textureId() const void QOpenGLWidgetPrivate::reset() { + Q_Q(QOpenGLWidget); + + // Destroy the OpenGL resources first. These need the context to be current. + if (initialized) + q->makeCurrent(); + delete paintDevice; paintDevice = 0; delete fbo; fbo = 0; delete resolvedFbo; resolvedFbo = 0; + + if (initialized) + q->doneCurrent(); + // Delete the context first, then the surface. Slots connected to // the context's aboutToBeDestroyed() may still call makeCurrent() // to perform some cleanup. -- cgit v1.2.3 From 6dac557fd3b9c913f1bc8b863bb676fc46df4b05 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 19 Nov 2014 12:05:27 +0100 Subject: Correct the signature and access rights for the protected constructor Change-Id: Ic43398a82777f3b1a95a36f60ebc4338d60c29ec Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qopenglwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 8a4e0c8ffd..23bb1f7050 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -471,7 +471,7 @@ class QOpenGLWidgetPaintDevice : public QOpenGLPaintDevice { public: QOpenGLWidgetPaintDevice(QOpenGLWidget *widget) - : QOpenGLPaintDevice(new QOpenGLWidgetPaintDevicePrivate(widget)) { } + : QOpenGLPaintDevice(*new QOpenGLWidgetPaintDevicePrivate(widget)) { } void ensureActiveTarget() Q_DECL_OVERRIDE; }; -- cgit v1.2.3 From cf0d96f4c8584a7eb9eeca304932f6ea88894b27 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 18 Nov 2014 12:19:22 +0100 Subject: QWidgetTextControl: Suppress drag selection for OS-synthesized mouse events. Add a convenience function to QApplicationPrivate returning the source of mouse events to be able to detect synthesized mouse events. Change-Id: I09f82ed917586cd3de8b4146fc6638d19d428163 Task-number: QTBUG-40461 Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qapplication.cpp | 26 ++++++++++++++++++++++++++ src/widgets/kernel/qapplication_p.h | 1 + 2 files changed, 27 insertions(+) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 269fe452c1..82b9fec37f 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -53,6 +53,7 @@ #include "qtranslator.h" #include "qvariant.h" #include "qwidget.h" +#include "qgraphicssceneevent.h" #include "private/qdnd_p.h" #include "private/qguiapplication_p.h" #include "qcolormap.h" @@ -2286,6 +2287,31 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool return w; } +Qt::MouseEventSource QApplicationPrivate::mouseEventSource(const QEvent *e) +{ + switch (e->type()) { + case QEvent::NonClientAreaMouseButtonDblClick: + case QEvent::NonClientAreaMouseButtonPress: + case QEvent::NonClientAreaMouseButtonRelease: + case QEvent::NonClientAreaMouseMove: + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + return static_cast(e)->source(); +#ifndef QT_NO_GRAPHICSVIEW + case QEvent::GraphicsSceneMouseDoubleClick: + case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseRelease: + case QEvent::GraphicsSceneMouseMove: + return static_cast(e)->source(); +#endif // !QT_NO_GRAPHICSVIEW + default: + break; + } + return Qt::MouseEventNotSynthesized; +} + /*! \fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF) \internal diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 7d97235c66..b24b592fbe 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -168,6 +168,7 @@ public: static void setFocusWidget(QWidget *focus, Qt::FocusReason reason); static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next, bool *wrappingOccurred = 0); + static Qt::MouseEventSource mouseEventSource(const QEvent *e); #ifndef QT_NO_GRAPHICSVIEW // Maintain a list of all scenes to ensure font and palette propagation to -- cgit v1.2.3 From 2ffa46054d13c639cf9f7846a74ad3ebd07b9f5c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 10 Nov 2014 10:52:22 +0100 Subject: Use single finger pan to scroll text edits on touch screens. Change the number of pan points to 1 for these classes as a workaround until pan/tap gestures are fully fixed. Task-number: QTBUG-40461 Change-Id: I0d68726a545ee6148f3ab88f2ab7308b10464ecd Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qstandardgestures.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp index 6656903e70..53e5d091fa 100644 --- a/src/widgets/kernel/qstandardgestures.cpp +++ b/src/widgets/kernel/qstandardgestures.cpp @@ -38,6 +38,7 @@ #include "qwidget.h" #include "qabstractscrollarea.h" #include +#include #include "qdebug.h" #ifndef QT_NO_GESTURES @@ -67,8 +68,26 @@ static QPointF panOffset(const QList &touchPoints, int return result / qreal(count); } +// ### fixme: Remove this +// Use single finger pan to scroll QPlainTextEdit/QTextEdit +// by changing the number of pan points to 1 for these classes. +// This used to be Qt 4's behavior on Windows which was achieved using native +// Windows gesture recognizers for these classes. +// The other classes inheriting QScrollArea still use standard 2 finger pan. +// In the long run, they should also use single finger pan to +// scroll on touch screens, however, this requires a distinct Tap&Hold-followed-by-pan +// type gesture to avoid clashes with item view selection and DnD. + +static inline int panTouchPoints(const QTouchEvent *event, const QObject *object, + int defaultTouchPoints) +{ + return event->device()->type() == QTouchDevice::TouchScreen && object && object->parent() + && (object->parent()->inherits("QPlainTextEdit") || object->parent()->inherits("QTextEdit")) + ? 1 : defaultTouchPoints; +} + QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, - QObject *, + QObject *object, QEvent *event) { QPanGesture *q = static_cast(state); @@ -81,7 +100,7 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, result = QGestureRecognizer::MayBeGesture; QTouchEvent::TouchPoint p = ev->touchPoints().at(0); d->lastOffset = d->offset = QPointF(); - d->pointCount = m_pointCount; + d->pointCount = panTouchPoints(ev, object, m_pointCount); break; } case QEvent::TouchEnd: { -- cgit v1.2.3