aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarno Malmari <ext-jarno.malmari@nokia.com>2010-12-13 16:09:37 +0200
committerAdrian Yanes <ext-adrian.yanes@nokia.com>2010-12-21 10:24:00 +0100
commit90a9bbbc6fb8ca1b085a58c749e4cc492c38c449 (patch)
tree46a3260dfa812564cb91d6575018eb784dd5235f
parentee883860797c0d91aa2e1a8a4f9ff44e55275319 (diff)
Fixes: NB#210697, [REG] Text Input Field is moved up while focus is set
RevBy: Michael Hasselmann, MichaƂ Guminiak Details: Introduced a custom dynamic property which controls whether a scrollable widget can be docked to vkb.
-rw-r--r--src/corelib/core/minputwidgetrelocator.cpp75
-rw-r--r--src/corelib/core/minputwidgetrelocator.h6
-rw-r--r--src/corelib/core/mscrollchain.cpp27
-rw-r--r--src/corelib/core/mscrollchain.h11
-rw-r--r--tests/ut_minputwidgetrelocator/ut_minputwidgetrelocator.cpp9
5 files changed, 123 insertions, 5 deletions
diff --git a/src/corelib/core/minputwidgetrelocator.cpp b/src/corelib/core/minputwidgetrelocator.cpp
index 8d2e2f75..0187358c 100644
--- a/src/corelib/core/minputwidgetrelocator.cpp
+++ b/src/corelib/core/minputwidgetrelocator.cpp
@@ -28,12 +28,13 @@
#include "mrelocatorstyle.h"
#include "mscrollchain.h"
-#include <QDebug>
#include <QGraphicsScene>
#include <QGraphicsWidget>
-#include <QTimer>
namespace {
+
+ const char * const BottomDockingProperty = "dockBottom";
+
bool widgetDoesNotWantToBeScrolled(const QGraphicsWidget *widget)
{
// We don't know where to scroll QGraphicsWebView. We would only make things worse by trying.
@@ -133,9 +134,11 @@ void MInputWidgetRelocator::update()
const QRect microRect(microFocusRect(inputWidget));
if (microRect.isValid() && newChain->count() > 0) {
+ const bool widgetWasDocked = scrollDockedWidget(newChain, inputWidget, microRect);
- // Check whether we need to do anything.
- if (needsRelocation(inputWidget, microRect)) {
+ // If widget was not docked then use the regular rules with nogo zones
+ // and an anchor point.
+ if (!widgetWasDocked && needsRelocation(inputWidget, microRect)) {
// Calculate anchor point in root coordinates
const QPoint anchorPoint(rootElement->mapFromItem(inputWidget, microRect.topLeft()).x(),
@@ -334,7 +337,68 @@ bool MInputWidgetRelocator::isWidgetRectFullyVisible(const QGraphicsWidget *widg
{
// Widget can be clipped by a nested pannable viewport.
return !widget->isClipped()
- || widget->clipPath().contains(localRect);
+ || widget->clipPath().boundingRect().contains(localRect);
+}
+
+bool MInputWidgetRelocator::scrollDockedWidget(MScrollChain *chain,
+ const QGraphicsWidget *inputWidget,
+ const QRect &microRect)
+{
+ // Find if we have scroller that wants to be docked to bottom.
+ const QGraphicsWidget *dockWidget = 0;
+ int dockWidgetId = -1;
+ for (int i = 0; i < chain->count(); ++i) {
+ QVariant dockBottom(chain->widgetAt(i)->property(BottomDockingProperty));
+ if (dockBottom.isValid()
+ && dockBottom.toBool()) {
+ dockWidgetId = i;
+ dockWidget = chain->widgetAt(i);
+ break;
+ }
+ }
+
+ if (!dockWidget) {
+ return false;
+ }
+
+ // This is the rectangle we need to dock and preferably even keep it fully visible.
+ const QRect dockWidgetRect(dockWidget->rect().toRect());
+
+ // Origin of the rectangle has to be given to the chain in inputWidget coordinates.
+ const QPoint originPoint = inputWidget->mapFromItem(dockWidget,
+ dockWidgetRect.topLeft()).toPoint();
+
+ // Calculate target rectangle for the widget to be docked.
+ QRect targetRect = rootElement->mapRectFromItem(dockWidget, dockWidgetRect).toRect();
+
+ bool chainChanged = false;
+
+ // Dock the widget if only it's not already at correct position.
+ if (targetRect.bottom() != exposedContentRect().bottom()
+ || !isWidgetRectFullyVisible(dockWidget, dockWidgetRect)) {
+
+ // Move it to bottom of exposed content rectangle.
+ targetRect.moveBottom(exposedContentRect().bottom());
+
+ // Docking is done by parents of the dockWidget, therefore start at the next scroller.
+ chain->addBottomUpScroll(targetRect, originPoint, dockWidgetId + 1);
+
+ chainChanged = true;
+ }
+
+ // We still need to bring cursor visible, although we cannot guarantee it because
+ // docking at a right place is of higher priority. Use dockWidget and its children
+ // scrollers to scroll cursor rectangle visible. Don't touch parents of dockWidget.
+ if (!isWidgetRectFullyVisible(inputWidget, microRect)) {
+ chain->addMinimalScroll(microRect, 0, dockWidgetId);
+ chainChanged = true;
+ }
+
+ if (chainChanged) {
+ chain->applyScrolling();
+ }
+
+ return true;
}
void MInputWidgetRelocator::centerContextWidgetToAnchorPoint(MScrollChain *newChain,
@@ -345,6 +409,7 @@ void MInputWidgetRelocator::centerContextWidgetToAnchorPoint(MScrollChain *newCh
const int yTarget = qMax<int>(exposedContentRect().top(),
anchorPoint.y() - contextWidget->size().height() / 2);
const QRect targetRect(QPoint(anchorPoint.x(), yTarget), contextWidget->size().toSize());
+
const QPoint originPoint(contextWidget->mapToItem(inputWidget, 0, 0).toPoint());
newChain->addBottomUpScroll(targetRect, originPoint, 1);
}
diff --git a/src/corelib/core/minputwidgetrelocator.h b/src/corelib/core/minputwidgetrelocator.h
index 158ca9b6..c79233de 100644
--- a/src/corelib/core/minputwidgetrelocator.h
+++ b/src/corelib/core/minputwidgetrelocator.h
@@ -133,6 +133,12 @@ private:
bool isWidgetRectFullyVisible(const QGraphicsWidget *widget,
const QRect &localRect) const;
+ //! If chain contains a dockable widget, dock it and return true.
+ //! Otherwise return false.
+ bool scrollDockedWidget(MScrollChain *chain,
+ const QGraphicsWidget *inputWidget,
+ const QRect &microRect);
+
void centerContextWidgetToAnchorPoint(MScrollChain *newChain,
const QPoint &anchorPoint,
const QGraphicsWidget *inputWidget);
diff --git a/src/corelib/core/mscrollchain.cpp b/src/corelib/core/mscrollchain.cpp
index a292ec32..0d4ecd7f 100644
--- a/src/corelib/core/mscrollchain.cpp
+++ b/src/corelib/core/mscrollchain.cpp
@@ -61,6 +61,24 @@ void MScrollChain::addBottomUpScroll(const QRect &targetRect,
}
}
+void MScrollChain::addMinimalScroll(const QRect &localRect,
+ int startingIndex,
+ int untilIndex)
+{
+ untilIndex = qBound<int>(0, untilIndex, chainItems.count() - 1);
+ startingIndex = qBound<int>(0, startingIndex, untilIndex);
+
+ for (int i = startingIndex; i <= untilIndex; ++i) {
+ ScrollChainItem &chainItem(chainItems[i]);
+
+ // Map target rectangle and origin point to delegate widget's local coordinates.
+ QRect delegateRect = mapToChainItemFromScrollTarget(chainItem, localRect);
+
+ // Scroll the chain item.
+ chainItem.calculateScrolling(delegateRect, delegateRect.topLeft());
+ }
+}
+
void MScrollChain::applyScrolling()
{
for (ChainItemList::iterator item = chainItems.begin(); item != chainItems.end(); ++item) {
@@ -198,6 +216,15 @@ QPoint MScrollChain::mapToChainItemFromScrollTarget(const ScrollChainItem &item,
return mappedPoint;
}
+
+QRect MScrollChain::mapToChainItemFromScrollTarget(const ScrollChainItem &item,
+ const QRect &rect)
+{
+ QRect moved = rect;
+ moved.moveTo(mapToChainItemFromScrollTarget(item, rect.topLeft()));
+ return moved;
+}
+
QSharedPointer<MAbstractScroller> MScrollChain::findScrollerDelegate(const QGraphicsWidget *widget) const
{
QSharedPointer<MAbstractScroller> result;
diff --git a/src/corelib/core/mscrollchain.h b/src/corelib/core/mscrollchain.h
index c2c3d29b..95df896c 100644
--- a/src/corelib/core/mscrollchain.h
+++ b/src/corelib/core/mscrollchain.h
@@ -73,6 +73,15 @@ public:
const QPoint &originPoint,
int startingIndex = 0);
+ /*! \brief Scrolls the chain with minimal change in child-to-parent order.
+ *
+ * Calling this ensures that the given \localRect is made visible with
+ * minimal scrolling.
+ */
+ void addMinimalScroll(const QRect &localRect,
+ int startingIndex,
+ int untilIndex);
+
/*! \brief Applies the planned scrolling
*
* Widgets are not expected to have finished their scrolling when this returns.
@@ -142,6 +151,8 @@ private:
QRect mapToChainItemFromRoot(const ScrollChainItem &item, const QRect &rect) const;
QPoint mapToChainItemFromRoot(const ScrollChainItem &item, const QPoint &point) const;
QPoint mapToChainItemFromScrollTarget(const ScrollChainItem &item, const QPoint &point);
+ QRect mapToChainItemFromScrollTarget(const ScrollChainItem &item,
+ const QRect &rect);
private:
typedef QMap<const QMetaObject *, QSharedPointer<MAbstractScroller> > ScrollerDelegateMap;
diff --git a/tests/ut_minputwidgetrelocator/ut_minputwidgetrelocator.cpp b/tests/ut_minputwidgetrelocator/ut_minputwidgetrelocator.cpp
index 123e77f9..e065965b 100644
--- a/tests/ut_minputwidgetrelocator/ut_minputwidgetrelocator.cpp
+++ b/tests/ut_minputwidgetrelocator/ut_minputwidgetrelocator.cpp
@@ -380,6 +380,15 @@ void MScrollChain::addBottomUpScroll(const QRect &targetRect, const QPoint &orig
Q_UNUSED(index);
}
+void MScrollChain::addMinimalScroll(const QRect &localRect,
+ int startingIndex,
+ int untilIndex)
+{
+ Q_UNUSED(localRect);
+ Q_UNUSED(startingIndex);
+ Q_UNUSED(untilIndex);
+}
+
void MScrollChain::applyScrolling()
{
++gScrollCallCount;