[Libreoffice-commits] core.git: 16 commits - android/experimental android/README editeng/source sd/qa sd/source sw/qa sw/source

Miklos Vajna vmiklos at collabora.co.uk
Mon Apr 13 00:08:07 PDT 2015


 android/README                                                                            |    6 
 android/experimental/LOAndroid3/res/layout/text_selection_handles.xml                     |    2 
 android/experimental/LOAndroid3/res/menu/main.xml                                         |   12 
 android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java         |  108 ++
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java                  |   13 
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java                 |    1 
 android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java     |   10 
 android/experimental/LOAndroid3/src/java/org/libreoffice/canvas/Cursor.java               |   38 
 android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java     |  210 +++++
 android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlayView.java |  373 +++++++++
 android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorLayer.java     |  200 -----
 android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java      |  381 ----------
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java      |    9 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java |   24 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java        |    2 
 editeng/source/editeng/editview.cxx                                                       |    3 
 sd/qa/unit/tiledrendering/tiledrendering.cxx                                              |   28 
 sd/source/ui/inc/ViewShell.hxx                                                            |    2 
 sd/source/ui/unoidl/unomodel.cxx                                                          |    6 
 sd/source/ui/view/viewshel.cxx                                                            |    2 
 sw/qa/extras/tiledrendering/tiledrendering.cxx                                            |   18 
 sw/source/uibase/docvw/edtwin.cxx                                                         |    2 
 sw/source/uibase/inc/edtwin.hxx                                                           |    2 
 sw/source/uibase/uno/unotxdoc.cxx                                                         |    6 
 24 files changed, 819 insertions(+), 639 deletions(-)

New commits:
commit 6eaf6c8d2344fb4ef55c8d1178433588701bdd6b
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Apr 10 16:36:42 2015 +0200

    android: move strikeout button after underline
    
    So that it matches the order we show on the desktop.
    
    Change-Id: Ia5be2a233bc4ab3adc37b013b22784032d58a174

diff --git a/android/experimental/LOAndroid3/res/menu/main.xml b/android/experimental/LOAndroid3/res/menu/main.xml
index 09314f5..1ab1ef1 100644
--- a/android/experimental/LOAndroid3/res/menu/main.xml
+++ b/android/experimental/LOAndroid3/res/menu/main.xml
@@ -16,18 +16,18 @@
           android:orderInCategory="100"
           app:showAsAction="always"/>
 
-    <item android:id="@+id/action_strikeout"
-          android:title="@string/action_strikeout"
-          android:icon="@drawable/action_strikeout"
-          android:orderInCategory="100"
-          app:showAsAction="always"/>
-
     <item android:id="@+id/action_underline"
           android:title="@string/action_underline"
           android:icon="@drawable/action_underline"
           android:orderInCategory="100"
           app:showAsAction="always"/>
 
+    <item android:id="@+id/action_strikeout"
+          android:title="@string/action_strikeout"
+          android:icon="@drawable/action_strikeout"
+          android:orderInCategory="100"
+          app:showAsAction="always"/>
+
     <item android:id="@+id/action_keyboard"
           android:title="@string/action_keyboard"
           android:icon="@drawable/ic_format_keyboard_grey600_24dp"
commit 54eaeabdf7d90ee05e9eb8d4deab8d7e1d8ed150
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Apr 10 16:09:20 2015 +0200

    Add SdXImpressDocument::postKeyEvent() testcase.
    
    Change-Id: I87edb9c4693b1634942d8dbda4050920f439cbbf

diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 5a364c4..1b87768 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -40,6 +40,7 @@ public:
 
 #if !defined(WNT) && !defined(MACOSX)
     void testRegisterCallback();
+    void testPostKeyEvent();
     void testPostMouseEvent();
     void testSetTextSelection();
 #endif
@@ -47,6 +48,7 @@ public:
     CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
 #if !defined(WNT) && !defined(MACOSX)
     CPPUNIT_TEST(testRegisterCallback);
+    CPPUNIT_TEST(testPostKeyEvent);
     CPPUNIT_TEST(testPostMouseEvent);
     CPPUNIT_TEST(testSetTextSelection);
 #endif
@@ -137,6 +139,32 @@ void SdTiledRenderingTest::testRegisterCallback()
     CPPUNIT_ASSERT(m_aInvalidation.IsOver(aTopLeft));
 }
 
+void SdTiledRenderingTest::testPostKeyEvent()
+{
+    SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+    sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+    SdPage* pActualPage = pViewShell->GetActualPage();
+    SdrObject* pObject = pActualPage->GetObj(0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(OBJ_TITLETEXT), pObject->GetObjIdentifier());
+    SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
+    SdrView* pView = pViewShell->GetView();
+    pView->MarkObj(pTextObj, pView->GetSdrPageView());
+    SfxStringItem aInputString(SID_ATTR_CHAR, "x");
+    pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_ATTR_CHAR, SfxCallMode::SYNCHRON, &aInputString, 0);
+
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+
+    CPPUNIT_ASSERT(pView->GetTextEditObject());
+    EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+    // Did we manage to enter a second character?
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), rEditView.GetSelection().nStartPos);
+    ESelection aWordSelection(0, 0, 0, 2); // start para, start char, end para, end char.
+    rEditView.SetSelection(aWordSelection);
+    // Did we enter the expected character?
+    CPPUNIT_ASSERT_EQUAL(OUString("xx"), rEditView.GetSelected());
+}
+
 void SdTiledRenderingTest::testPostMouseEvent()
 {
     SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
commit c09c3559f011e89ae45c16e5cf0bb085e127f0ea
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Apr 10 16:15:27 2015 +0200

    Fix failing SdTiledRenderingTest::testSetTextSelection().
    
    Change-Id: Ieaeaef249ea15de7cebc1cdb60b4d6130a6b5616

diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx
index 6d0c556..d407e4e 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -1323,14 +1323,17 @@ void EditView::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool
 {
     Point aDocPos(pImpEditView->GetDocPos(rPosition));
     EditPaM aPaM = pImpEditView->pEditEngine->GetPaM(aDocPos);
+    EditSelection aSelection(pImpEditView->GetEditSelection());
 
     // Explicitly create or delete the selection.
     if (bClearMark)
+    {
         pImpEditView->DeselectAll();
+        aSelection = pImpEditView->GetEditSelection();
+    }
     else
         pImpEditView->CreateAnchor();
 
-    EditSelection aSelection(pImpEditView->GetEditSelection());
     if (bPoint)
         aSelection.Max() = aPaM;
     else
commit 060dcbf6d118cef164c75a8cb603d6a4179abf53
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Apr 10 15:23:29 2015 +0200

    EditView::SetCursorLogicPosition: first deselect, then get the selection
    
    If you tap to nearly the end of an editeng paragraph, then drag the
    cursor using EditView::SetCursorLogicPosition(bPoint=true,
    bClearMark=true) to the end of the paragraph, finally hit enter, the
    text between the tap position and the end of the paragraph gets deleted.
    
    Fix this by calling GetEditSelection() after DeselectAll(), so that the
    original cursor position (before the drag started) never survives, which
    gives back the lost text, too.
    
    Change-Id: I777256765f1c8f1a7f22c549eaca19e575fdae21

diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx
index 11d041d..6d0c556 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -1323,7 +1323,6 @@ void EditView::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool
 {
     Point aDocPos(pImpEditView->GetDocPos(rPosition));
     EditPaM aPaM = pImpEditView->pEditEngine->GetPaM(aDocPos);
-    EditSelection aSelection(pImpEditView->GetEditSelection());
 
     // Explicitly create or delete the selection.
     if (bClearMark)
@@ -1331,6 +1330,7 @@ void EditView::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool
     else
         pImpEditView->CreateAnchor();
 
+    EditSelection aSelection(pImpEditView->GetEditSelection());
     if (bPoint)
         aSelection.Max() = aPaM;
     else
commit 2cd35b8ddfe8fa6504cea0cf55f8dbaf15c9e530
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Apr 10 15:15:41 2015 +0200

    sw: SetCursorLogicPosition -> SetCursorTwipPosition
    
    Again, to be consistent with SetGraphicTwipPosition.
    
    Change-Id: Id2134de9ec8467b890ff6f26a3d538fbb45ad3e0

diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 42c41f3..14c45ed 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -6209,7 +6209,7 @@ void SwEditWin::LogicMouseButtonUp(const MouseEvent& rMouseEvent)
     SetPointerPosPixel(aPoint);
 }
 
-void SwEditWin::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
+void SwEditWin::SetCursorTwipPosition(const Point& rPosition, bool bPoint, bool bClearMark)
 {
     if (SdrView* pSdrView = m_rView.GetWrtShell().GetDrawView())
     {
diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx
index e8c2e5e..ae96136 100644
--- a/sw/source/uibase/inc/edtwin.hxx
+++ b/sw/source/uibase/inc/edtwin.hxx
@@ -303,7 +303,7 @@ public:
     /// Same as MouseButtonUp(), but coordinates are in logic unit.
     void LogicMouseButtonUp(const MouseEvent& rMouseEvent);
     /// Allows adjusting the point or mark of the selection to a document coordinate.
-    void SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark);
+    void SetCursorTwipPosition(const Point& rPosition, bool bPoint, bool bClearMark);
     /// Allows starting or ending a graphic move or resize action.
     void SetGraphicTwipPosition(bool bStart, const Point& rPosition);
 };
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 5feadbf..0dca9b0 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3233,13 +3233,13 @@ void SwXTextDocument::setTextSelection(int nType, int nX, int nY)
     switch (nType)
     {
     case LOK_SETTEXTSELECTION_START:
-        rEditWin.SetCursorLogicPosition(Point(nX, nY), /*bPoint=*/false, /*bClearMark=*/false);
+        rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/false, /*bClearMark=*/false);
         break;
     case LOK_SETTEXTSELECTION_END:
-        rEditWin.SetCursorLogicPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/false);
+        rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/false);
         break;
     case LOK_SETTEXTSELECTION_RESET:
-        rEditWin.SetCursorLogicPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/true);
+        rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/true);
         break;
     default:
         assert(false);
commit f37952bb2531f8fe25fc6f793bf85280fa774356
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Apr 10 14:58:53 2015 +0200

    sd: SetCursorLogicPosition -> SetCursorMm100Position
    
    To be consistent with SetGraphicMm100Position.
    
    Change-Id: Ic6775f9f1350ceb41381b4090cd32c4bd4393e67

diff --git a/sd/source/ui/inc/ViewShell.hxx b/sd/source/ui/inc/ViewShell.hxx
index 93bb0f9..6d8ba40 100644
--- a/sd/source/ui/inc/ViewShell.hxx
+++ b/sd/source/ui/inc/ViewShell.hxx
@@ -448,7 +448,7 @@ public:
     /// Same as MouseButtonUp(), but coordinates are in logic unit.
     void LogicMouseButtonUp(const MouseEvent& rMouseEvent);
     /// Allows adjusting the point or mark of the selection to a document coordinate.
-    void SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark);
+    void SetCursorMm100Position(const Point& rPosition, bool bPoint, bool bClearMark);
     /// Allows starting or ending a graphic move or resize action.
     void SetGraphicMm100Position(bool bStart, const Point& rPosition);
 
diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx
index bdf49e9..bc2c3e0 100644
--- a/sd/source/ui/unoidl/unomodel.cxx
+++ b/sd/source/ui/unoidl/unomodel.cxx
@@ -2442,13 +2442,13 @@ void SdXImpressDocument::setTextSelection(int nType, int nX, int nY)
     switch (nType)
     {
     case LOK_SETTEXTSELECTION_START:
-        pViewShell->SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
+        pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
         break;
     case LOK_SETTEXTSELECTION_END:
-        pViewShell->SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
+        pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
         break;
     case LOK_SETTEXTSELECTION_RESET:
-        pViewShell->SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
+        pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
         break;
     default:
         assert(false);
diff --git a/sd/source/ui/view/viewshel.cxx b/sd/source/ui/view/viewshel.cxx
index 4016503..4e51b2e 100644
--- a/sd/source/ui/view/viewshel.cxx
+++ b/sd/source/ui/view/viewshel.cxx
@@ -532,7 +532,7 @@ void ViewShell::LogicMouseButtonUp(const MouseEvent& rMouseEvent)
     mpActiveWindow->SetPointerPosPixel(aPoint);
 }
 
-void ViewShell::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark)
+void ViewShell::SetCursorMm100Position(const Point& rPosition, bool bPoint, bool bClearMark)
 {
     if (SdrView* pSdrView = GetView())
     {
commit 7f0dfb3ae67bd8ce64fbbea3b418071faee1a6a0
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Apr 9 17:27:31 2015 +0900

    android: tune the viewport moving to cursor position on key input
    
    Change-Id: Ie420307f28cc05ca03fabe47f46712f67c6f18fa

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index 9f83006..1fdc681 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -8,6 +8,8 @@ import android.net.Uri;
 import org.libreoffice.canvas.SelectionHandle;
 import org.libreoffice.kit.Document;
 import org.libreoffice.overlay.DocumentOverlay;
+import org.mozilla.gecko.gfx.GeckoLayerClient;
+import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -19,11 +21,13 @@ import java.util.List;
 public class InvalidationHandler implements Document.MessageCallback {
     private static String LOGTAG = InvalidationHandler.class.getSimpleName();
     private final DocumentOverlay mDocumentOverlay;
+    private final GeckoLayerClient mLayerClient;
     private OverlayState mState;
     private boolean mKeyEvent = false;
 
     public InvalidationHandler(LibreOfficeMainActivity mainActivity) {
         mDocumentOverlay = mainActivity.getDocumentOverlay();
+        mLayerClient = mainActivity.getLayerClient();
         mState = OverlayState.NONE;
     }
 
@@ -153,8 +157,7 @@ public class InvalidationHandler implements Document.MessageCallback {
             mDocumentOverlay.positionHandle(SelectionHandle.HandleType.MIDDLE, cursorRectangle);
 
             if (mKeyEvent) {
-                PointF point = new PointF(cursorRectangle.centerX(), cursorRectangle.centerY());
-                LOKitShell.moveViewportTo(point, null);
+                moveViewportToMakeCursorVisible(cursorRectangle);
                 mKeyEvent = false;
             }
 
@@ -165,6 +168,37 @@ public class InvalidationHandler implements Document.MessageCallback {
     }
 
     /**
+     * Move the viewport to show the cursor. The cursor will appear at the
+     * viewport position depending on where the cursor is relative to the
+     * viewport (either cursor is above, below, on left or right).
+     *
+     * @param cursorRectangle - cursor position on the document
+     */
+    public void moveViewportToMakeCursorVisible(RectF cursorRectangle) {
+        RectF moveToRect = mLayerClient.getViewportMetrics().getCssViewport();
+        if (moveToRect.contains(cursorRectangle)) {
+            return;
+        }
+
+        float newLeft = moveToRect.left;
+        float newTop = moveToRect.top;
+
+        if (cursorRectangle.right < moveToRect.left || cursorRectangle.left < moveToRect.left) {
+            newLeft = cursorRectangle.left -  (moveToRect.width() * 0.1f);
+        } else if (cursorRectangle.right > moveToRect.right || cursorRectangle.left > moveToRect.right) {
+            newLeft = cursorRectangle.right - (moveToRect.width() * 0.9f);
+        }
+
+        if (cursorRectangle.top < moveToRect.top || cursorRectangle.bottom < moveToRect.top) {
+            newTop = cursorRectangle.top - (moveToRect.height() * 0.1f);
+        } else if (cursorRectangle.bottom > moveToRect.bottom || cursorRectangle.top > moveToRect.bottom) {
+            newTop = cursorRectangle.bottom - (moveToRect.height() / 2.0f);
+        }
+
+        LOKitShell.moveViewportTo(new PointF(newLeft, newTop), null);
+    }
+
+    /**
      * Handles the text selection start message
      *
      * @param payload
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
index 99f9948..d9a20d8 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
@@ -158,7 +158,7 @@ public class LOKitShell {
     }
 
     /**
-     * Move the viewport to the desired point, and change the zoom level.
+     * Move the viewport to the desired point (top-left), and change the zoom level.
      * Ensure this runs on the UI thread.
      */
     public static void moveViewportTo(final PointF position, final Float zoom) {
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
index f758681..f8b39b4 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
@@ -418,7 +418,7 @@ public class JavaPanZoomController
         } else {
             setState(PanZoomState.PANNING);
         }
-        LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
+        //LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
     }
 
     private float panDistance(MotionEvent move) {
@@ -1023,16 +1023,15 @@ public class JavaPanZoomController
     }
 
     /**
-     * Move to centerPosition and zoom to the desired input zoom factor. Input zoom
-     * factor can be null, in this case leave the zoom unchanged.
+     * Move the viewport to the top-left point to and zoom to the desired
+     * zoom factor. Input zoom factor can be null, in this case leave the zoom unchanged.
      */
-    public boolean animatedMove(PointF centerPoint, Float zoom) {
+    public boolean animatedMove(PointF topLeft, Float zoom) {
         RectF moveToRect = getMetrics().getCssViewport();
-        moveToRect.offsetTo(
-                centerPoint.x - moveToRect.width() / 2.0f,
-                centerPoint.y - moveToRect.height() / 2.0f);
+        moveToRect.offsetTo(topLeft.x, topLeft.y);
 
         ImmutableViewportMetrics finalMetrics = getMetrics();
+
         finalMetrics = finalMetrics.setViewportOrigin(
                 moveToRect.left * finalMetrics.zoomFactor,
                 moveToRect.top * finalMetrics.zoomFactor);
commit 207142748b095252f5c9bfd1b418a892823304d0
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Apr 8 17:48:21 2015 +0200

    Add SwXTextDocument::postKeyEvent() testcase.
    
    Change-Id: I76904ed9596dcb0b6aa70bccd19279573687d30c

diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index 23d3fe2..67c04db 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -15,6 +15,7 @@
 #include <vcl/svapp.hxx>
 #include <crsskip.hxx>
 #include <drawdoc.hxx>
+#include <ndtxt.hxx>
 #include <wrtsh.hxx>
 
 static const char* DATA_DIRECTORY = "/sw/qa/extras/tiledrendering/data/";
@@ -24,6 +25,7 @@ class SwTiledRenderingTest : public SwModelTestBase
 {
 public:
     void testRegisterCallback();
+    void testPostKeyEvent();
     void testPostMouseEvent();
     void testSetTextSelection();
     void testSetGraphicSelection();
@@ -31,6 +33,7 @@ public:
 
     CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
     CPPUNIT_TEST(testRegisterCallback);
+    CPPUNIT_TEST(testPostKeyEvent);
     CPPUNIT_TEST(testPostMouseEvent);
     CPPUNIT_TEST(testSetTextSelection);
     CPPUNIT_TEST(testSetGraphicSelection);
@@ -110,6 +113,21 @@ void SwTiledRenderingTest::testRegisterCallback()
 #endif
 }
 
+void SwTiledRenderingTest::testPostKeyEvent()
+{
+    SwXTextDocument* pXTextDocument = createDoc("dummy.fodt");
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+    SwShellCrsr* pShellCrsr = pWrtShell->getShellCrsr(false);
+    // Did we manage to go after the first character?
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), pShellCrsr->GetPoint()->nContent.GetIndex());
+
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+    // Did we manage to insert the character after the first one?
+    CPPUNIT_ASSERT_EQUAL(OUString("Axaa bbb."), pShellCrsr->GetPoint()->nNode.GetNode().GetTxtNode()->GetTxt());
+}
+
 void SwTiledRenderingTest::testPostMouseEvent()
 {
     SwXTextDocument* pXTextDocument = createDoc("dummy.fodt");
commit 3e6d192b048b4742a5cf522c1414aaa6a7ed3dee
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 8 18:57:55 2015 +0900

    android: hide keyboard on scrolling at a more correct location
    
    When animation happens the scrollbars appear. This hides the
    keyboard when the user types and the viewport is repositioned.
    With this change, trigger the keyboard hiding only when we really
    do scrolling (panning).
    
    Change-Id: I17dc651a6641e807a386d5184868412dd6710a28

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
index 0811c26..f758681 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
@@ -418,6 +418,7 @@ public class JavaPanZoomController
         } else {
             setState(PanZoomState.PANNING);
         }
+        LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
     }
 
     private float panDistance(MotionEvent move) {
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java
index 589bc7a..09229d8 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ScrollbarLayer.java
@@ -208,8 +208,6 @@ public class ScrollbarLayer extends TileLayer {
         mOpacity = 1.0f;
         endTransaction();
 
-        // Scrollbar is now visible, scrolling will start: hide the soft keyboard.
-        LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
         return true;
     }
 
commit 5d7a203bdae1940e4846c4c42f5d733e4ffa4160
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 8 18:24:48 2015 +0900

    android: reposition the viewport to the cursor at key event
    
    Change-Id: I9b18001d0629e203bee41ebbf4a3bd57adfea88e

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index 7aeb573..9f83006 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -1,6 +1,7 @@
 package org.libreoffice;
 
 import android.content.Intent;
+import android.graphics.PointF;
 import android.graphics.RectF;
 import android.net.Uri;
 
@@ -19,6 +20,7 @@ public class InvalidationHandler implements Document.MessageCallback {
     private static String LOGTAG = InvalidationHandler.class.getSimpleName();
     private final DocumentOverlay mDocumentOverlay;
     private OverlayState mState;
+    private boolean mKeyEvent = false;
 
     public InvalidationHandler(LibreOfficeMainActivity mainActivity) {
         mDocumentOverlay = mainActivity.getDocumentOverlay();
@@ -150,6 +152,12 @@ public class InvalidationHandler implements Document.MessageCallback {
             mDocumentOverlay.positionCursor(cursorRectangle);
             mDocumentOverlay.positionHandle(SelectionHandle.HandleType.MIDDLE, cursorRectangle);
 
+            if (mKeyEvent) {
+                PointF point = new PointF(cursorRectangle.centerX(), cursorRectangle.centerY());
+                LOKitShell.moveViewportTo(point, null);
+                mKeyEvent = false;
+            }
+
             if (mState == OverlayState.TRANSITION || mState == OverlayState.CURSOR) {
                 changeStateTo(OverlayState.CURSOR);
             }
@@ -352,6 +360,10 @@ public class InvalidationHandler implements Document.MessageCallback {
         return mState;
     }
 
+    public void keyEvent() {
+        mKeyEvent = true;
+    }
+
     public enum OverlayState {
         /**
          * State where the overlay is empty
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index 1da85f3..cc21840 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -271,6 +271,7 @@ public class LOKitThread extends Thread {
         if (mTileProvider == null) {
             return;
         }
+        mInvalidationHandler.keyEvent();
         mTileProvider.sendKeyEvent(keyEvent);
     }
 
commit e585b1206905ba57e98483b8295f78a384291b01
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 8 18:23:16 2015 +0900

    android: don't need the cursor position from DocumentOverlay
    
    Change-Id: I79155f9c5c8df211b35137cc61430cebccb4cfe3

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
index d949a6b..40e4eaa 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
@@ -205,10 +205,6 @@ public class DocumentOverlay {
             }
         });
     }
-
-    public RectF getCursorPosition() {
-        return mDocumentOverlayView.getCursorPosition();
-    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlayView.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlayView.java
index 7d72d3e..c4866df 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlayView.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlayView.java
@@ -368,10 +368,6 @@ public class DocumentOverlayView extends View implements View.OnTouchListener {
         }
         return null;
     }
-
-    public RectF getCursorPosition() {
-        return mCursor.mPosition;
-    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 20382895558479a7a89a9893c2379b5dbdb0a64f
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 8 18:21:11 2015 +0900

    android: add possibility to move the viewport and zoom + animation
    
    Change-Id: I294ad30b1fdd7f1a3d5099304cc4f077034567b7

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
index 38c13ca..99f9948 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
@@ -156,6 +156,19 @@ public class LOKitShell {
     public static void sendNavigationClickEvent() {
         LOKitShell.sendEvent(new LOEvent(LOEvent.NAVIGATION_CLICK));
     }
+
+    /**
+     * Move the viewport to the desired point, and change the zoom level.
+     * Ensure this runs on the UI thread.
+     */
+    public static void moveViewportTo(final PointF position, final Float zoom) {
+        getLayerView().getLayerClient().post(new Runnable() {
+            @Override
+            public void run() {
+                getLayerView().getLayerClient().moveTo(position, zoom);
+            }
+        });
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index 40fb8bb..bb6e3d0 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -324,6 +324,15 @@ public class GeckoLayerClient implements PanZoomTarget {
         }
     }
 
+    /**
+     * Move the viewport to the desired point, and change the zoom level.
+     */
+    public void moveTo(PointF point, Float zoom) {
+        if (mPanZoomController instanceof JavaPanZoomController) {
+            ((JavaPanZoomController) mPanZoomController).animatedMove(point, zoom);
+        }
+    }
+
     public void zoomTo(float pageWidth, float pageHeight) {
         zoomTo(new RectF(0, 0, pageWidth, pageHeight));
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
index adae23a..0811c26 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
@@ -1021,6 +1021,30 @@ public class JavaPanZoomController
         return true;
     }
 
+    /**
+     * Move to centerPosition and zoom to the desired input zoom factor. Input zoom
+     * factor can be null, in this case leave the zoom unchanged.
+     */
+    public boolean animatedMove(PointF centerPoint, Float zoom) {
+        RectF moveToRect = getMetrics().getCssViewport();
+        moveToRect.offsetTo(
+                centerPoint.x - moveToRect.width() / 2.0f,
+                centerPoint.y - moveToRect.height() / 2.0f);
+
+        ImmutableViewportMetrics finalMetrics = getMetrics();
+        finalMetrics = finalMetrics.setViewportOrigin(
+                moveToRect.left * finalMetrics.zoomFactor,
+                moveToRect.top * finalMetrics.zoomFactor);
+
+        if (zoom != null) {
+            finalMetrics = finalMetrics.scaleTo(zoom, new PointF(0.0f, 0.0f));
+        }
+        finalMetrics = getValidViewportMetrics(finalMetrics);
+
+        bounce(finalMetrics, PanZoomState.ANIMATED_ZOOM);
+        return true;
+    }
+
     /** This function must be called from the UI thread. */
     public void abortPanning() {
         checkMainThread();
commit 6cbcde026784ab279e2ea2e03d65e992fb7cb110
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 8 13:27:36 2015 +0900

    android: separate layer functionality to DocumentOverlayLayer
    
    Change-Id: Ie69259dbc5826dafbaebc8eec08163256b459337

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
index d28f33d..d949a6b 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
@@ -26,43 +26,52 @@ import java.util.List;
  * to setup the document overlay view, report visibility and position of its elements
  * when they change and report any changes to the viewport.
  */
-public class DocumentOverlay extends Layer {
+public class DocumentOverlay {
     private static final String LOGTAG = DocumentOverlay.class.getSimpleName();
 
-    private final DocumentOverlayView mCursorView;
-    private float mViewLeft;
-    private float mViewTop;
-    private float mViewZoom;
-
-    public DocumentOverlay(Activity context, LayerView layerView) {
-        mCursorView = (DocumentOverlayView) context.findViewById(R.id.text_cursor_view);
-        if (mCursorView == null) {
-            Log.e(LOGTAG, "Failed to initialize TextCursorLayer - CursorView is null");
-        }
-        layerView.addLayer(this);
-        mCursorView.initialize(layerView);
-    }
+    private final DocumentOverlayView mDocumentOverlayView;
+    private final DocumentOverlayLayer mDocumentOverlayLayer;
 
     /**
-     * @see Layer#draw(org.mozilla.gecko.gfx.Layer.RenderContext)
+     * DocumentOverlayLayer responsibility is to get the changes to the viewport
+     * and report them to DocumentOverlayView.
      */
-    @Override
-    public void draw(final RenderContext context) {
-        if (FloatUtils.fuzzyEquals(mViewLeft, context.viewport.left)
-                && FloatUtils.fuzzyEquals(mViewTop, context.viewport.top)
-                && FloatUtils.fuzzyEquals(mViewZoom, context.zoomFactor)) {
-            return;
-        }
+    private class DocumentOverlayLayer extends Layer {
+        private float mViewLeft;
+        private float mViewTop;
+        private float mViewZoom;
+
+        /**
+         * @see Layer#draw(org.mozilla.gecko.gfx.Layer.RenderContext)
+         */
+        @Override
+        public void draw(final RenderContext context) {
+            if (FloatUtils.fuzzyEquals(mViewLeft, context.viewport.left)
+                    && FloatUtils.fuzzyEquals(mViewTop, context.viewport.top)
+                    && FloatUtils.fuzzyEquals(mViewZoom, context.zoomFactor)) {
+                return;
+            }
 
-        mViewLeft = context.viewport.left;
-        mViewTop = context.viewport.top;
-        mViewZoom = context.zoomFactor;
+            mViewLeft = context.viewport.left;
+            mViewTop = context.viewport.top;
+            mViewZoom = context.zoomFactor;
 
-        LOKitShell.getMainHandler().post(new Runnable() {
-            public void run() {
-                mCursorView.repositionWithViewport(mViewLeft, mViewTop, mViewZoom);
-            }
-        });
+            LOKitShell.getMainHandler().post(new Runnable() {
+                public void run() {
+                    mDocumentOverlayView.repositionWithViewport(mViewLeft, mViewTop, mViewZoom);
+                }
+            });
+        }
+    }
+
+    public DocumentOverlay(Activity context, LayerView layerView) {
+        mDocumentOverlayView = (DocumentOverlayView) context.findViewById(R.id.text_cursor_view);
+        mDocumentOverlayLayer = new DocumentOverlayLayer();
+        if (mDocumentOverlayView == null) {
+            Log.e(LOGTAG, "Failed to initialize TextCursorLayer - CursorView is null");
+        }
+        layerView.addLayer(mDocumentOverlayLayer);
+        mDocumentOverlayView.initialize(layerView);
     }
 
     /**
@@ -71,7 +80,7 @@ public class DocumentOverlay extends Layer {
     public void showCursor() {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.showCursor();
+                mDocumentOverlayView.showCursor();
             }
         });
     }
@@ -82,7 +91,7 @@ public class DocumentOverlay extends Layer {
     public void hideCursor() {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.hideCursor();
+                mDocumentOverlayView.hideCursor();
             }
         });
     }
@@ -93,7 +102,7 @@ public class DocumentOverlay extends Layer {
     public void positionCursor(final RectF position) {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.changeCursorPosition(position);
+                mDocumentOverlayView.changeCursorPosition(position);
             }
         });
     }
@@ -104,7 +113,7 @@ public class DocumentOverlay extends Layer {
     public void showSelections() {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.showSelections();
+                mDocumentOverlayView.showSelections();
             }
         });
     }
@@ -115,7 +124,7 @@ public class DocumentOverlay extends Layer {
     public void hideSelections() {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.hideSelections();
+                mDocumentOverlayView.hideSelections();
             }
         });
     }
@@ -126,7 +135,7 @@ public class DocumentOverlay extends Layer {
     public void changeSelections(final List<RectF> selections) {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.changeSelections(selections);
+                mDocumentOverlayView.changeSelections(selections);
             }
         });
     }
@@ -137,7 +146,7 @@ public class DocumentOverlay extends Layer {
     public void showGraphicSelection() {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.showGraphicSelection();
+                mDocumentOverlayView.showGraphicSelection();
             }
         });
     }
@@ -148,7 +157,7 @@ public class DocumentOverlay extends Layer {
     public void hideGraphicSelection() {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.hideGraphicSelection();
+                mDocumentOverlayView.hideGraphicSelection();
             }
         });
     }
@@ -159,7 +168,7 @@ public class DocumentOverlay extends Layer {
     public void changeGraphicSelection(final RectF rectangle) {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.changeGraphicSelection(rectangle);
+                mDocumentOverlayView.changeGraphicSelection(rectangle);
             }
         });
     }
@@ -170,7 +179,7 @@ public class DocumentOverlay extends Layer {
     public void showHandle(final SelectionHandle.HandleType type) {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.showHandle(type);
+                mDocumentOverlayView.showHandle(type);
             }
         });
     }
@@ -181,7 +190,7 @@ public class DocumentOverlay extends Layer {
     public void hideHandle(final SelectionHandle.HandleType type) {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.hideHandle(type);
+                mDocumentOverlayView.hideHandle(type);
             }
         });
     }
@@ -192,13 +201,13 @@ public class DocumentOverlay extends Layer {
     public void positionHandle(final SelectionHandle.HandleType type, final RectF rectangle) {
         LOKitShell.getMainHandler().post(new Runnable() {
             public void run() {
-                mCursorView.positionHandle(type, rectangle);
+                mDocumentOverlayView.positionHandle(type, rectangle);
             }
         });
     }
 
     public RectF getCursorPosition() {
-        return mCursorView.getCursorPosition();
+        return mDocumentOverlayView.getCursorPosition();
     }
 }
 
commit 5707813c075cdbccaf74dbdcb623dcf0149d5d1d
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 8 13:17:00 2015 +0900

    android: rename TextCursorLayer{View} -> DocumentOverlay{View}
    
    Change-Id: I53a55e2d30c298e7c34f18b7713de91f3c77d5f2

diff --git a/android/README b/android/README
index 0837900..0989cf6 100644
--- a/android/README
+++ b/android/README
@@ -144,9 +144,9 @@ Overlay
 
 Overlay elements like cursor and selections aren't drawn by the LO core, instead the core
 only provides data (cursor position, selection rectangles) and the app needs to draw them.
-TextCursorView (org.libreoffice.overlay.TextCursorView) and TextCursorLayer
-(org.libreoffice.overlay.TextCursorLayer) are the classes that provide the overlay over the
-document, where selections and the cursor is drawn.
+DocumentOverlay (org.libreoffice.overlay.DocumentOverlay) and DocumentOverlayView
+(org.libreoffice.overlay.DocumentOverlayView) are the classes that provide the overlay over 
+the document, where selections and the cursor is drawn.
 
 Emulator and debugging notes
 ****************************
diff --git a/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml b/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml
index b75ffd9..0be954d 100644
--- a/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml
+++ b/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml
@@ -6,7 +6,7 @@
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:gecko="http://schemas.android.com/apk/res-auto">
 
-    <org.libreoffice.overlay.TextCursorView
+    <org.libreoffice.overlay.DocumentOverlayView
         android:id="@+id/text_cursor_view"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"/>
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index a49b32d..7aeb573 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -6,7 +6,7 @@ import android.net.Uri;
 
 import org.libreoffice.canvas.SelectionHandle;
 import org.libreoffice.kit.Document;
-import org.libreoffice.overlay.TextCursorLayer;
+import org.libreoffice.overlay.DocumentOverlay;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -17,11 +17,11 @@ import java.util.List;
  */
 public class InvalidationHandler implements Document.MessageCallback {
     private static String LOGTAG = InvalidationHandler.class.getSimpleName();
-    private final TextCursorLayer mTextCursorLayer;
+    private final DocumentOverlay mDocumentOverlay;
     private OverlayState mState;
 
     public InvalidationHandler(LibreOfficeMainActivity mainActivity) {
-        mTextCursorLayer = mainActivity.getTextCursorLayer();
+        mDocumentOverlay = mainActivity.getDocumentOverlay();
         mState = OverlayState.NONE;
     }
 
@@ -147,8 +147,8 @@ public class InvalidationHandler implements Document.MessageCallback {
     private synchronized void invalidateCursor(String payload) {
         RectF cursorRectangle = convertPayloadToRectangle(payload);
         if (cursorRectangle != null) {
-            mTextCursorLayer.positionCursor(cursorRectangle);
-            mTextCursorLayer.positionHandle(SelectionHandle.HandleType.MIDDLE, cursorRectangle);
+            mDocumentOverlay.positionCursor(cursorRectangle);
+            mDocumentOverlay.positionHandle(SelectionHandle.HandleType.MIDDLE, cursorRectangle);
 
             if (mState == OverlayState.TRANSITION || mState == OverlayState.CURSOR) {
                 changeStateTo(OverlayState.CURSOR);
@@ -164,7 +164,7 @@ public class InvalidationHandler implements Document.MessageCallback {
     private synchronized void textSelectionStart(String payload) {
         RectF selectionRect = convertPayloadToRectangle(payload);
         if (selectionRect != null) {
-            mTextCursorLayer.positionHandle(SelectionHandle.HandleType.START, selectionRect);
+            mDocumentOverlay.positionHandle(SelectionHandle.HandleType.START, selectionRect);
         }
     }
 
@@ -176,7 +176,7 @@ public class InvalidationHandler implements Document.MessageCallback {
     private synchronized void textSelectionEnd(String payload) {
         RectF selectionRect = convertPayloadToRectangle(payload);
         if (selectionRect != null) {
-            mTextCursorLayer.positionHandle(SelectionHandle.HandleType.END, selectionRect);
+            mDocumentOverlay.positionHandle(SelectionHandle.HandleType.END, selectionRect);
         }
     }
 
@@ -190,14 +190,14 @@ public class InvalidationHandler implements Document.MessageCallback {
             if (mState == OverlayState.SELECTION) {
                 changeStateTo(OverlayState.TRANSITION);
             }
-            mTextCursorLayer.changeSelections(Collections.EMPTY_LIST);
+            mDocumentOverlay.changeSelections(Collections.EMPTY_LIST);
         } else {
             List<RectF> rectangles = convertPayloadToRectangles(payload);
             if (mState != OverlayState.SELECTION) {
                 changeStateTo(OverlayState.TRANSITION);
             }
             changeStateTo(OverlayState.SELECTION);
-            mTextCursorLayer.changeSelections(rectangles);
+            mDocumentOverlay.changeSelections(rectangles);
         }
     }
 
@@ -208,13 +208,13 @@ public class InvalidationHandler implements Document.MessageCallback {
      */
     private synchronized void cursorVisibility(String payload) {
         if (payload.equals("true")) {
-            mTextCursorLayer.showCursor();
+            mDocumentOverlay.showCursor();
             if (mState != OverlayState.SELECTION) {
-                mTextCursorLayer.showHandle(SelectionHandle.HandleType.MIDDLE);
+                mDocumentOverlay.showHandle(SelectionHandle.HandleType.MIDDLE);
             }
         } else if (payload.equals("false")) {
-            mTextCursorLayer.hideCursor();
-            mTextCursorLayer.hideHandle(SelectionHandle.HandleType.MIDDLE);
+            mDocumentOverlay.hideCursor();
+            mDocumentOverlay.hideHandle(SelectionHandle.HandleType.MIDDLE);
         }
     }
 
@@ -230,7 +230,7 @@ public class InvalidationHandler implements Document.MessageCallback {
             }
         } else {
             RectF rectangle = convertPayloadToRectangle(payload);
-            mTextCursorLayer.changeGraphicSelection(rectangle);
+            mDocumentOverlay.changeGraphicSelection(rectangle);
             if (mState != OverlayState.GRAPHIC_SELECTION) {
                 changeStateTo(OverlayState.TRANSITION);
             }
@@ -293,12 +293,12 @@ public class InvalidationHandler implements Document.MessageCallback {
         }
 
         // Just hide everything
-        mTextCursorLayer.hideHandle(SelectionHandle.HandleType.START);
-        mTextCursorLayer.hideHandle(SelectionHandle.HandleType.END);
-        mTextCursorLayer.hideHandle(SelectionHandle.HandleType.MIDDLE);
-        mTextCursorLayer.hideSelections();
-        mTextCursorLayer.hideCursor();
-        mTextCursorLayer.hideGraphicSelection();
+        mDocumentOverlay.hideHandle(SelectionHandle.HandleType.START);
+        mDocumentOverlay.hideHandle(SelectionHandle.HandleType.END);
+        mDocumentOverlay.hideHandle(SelectionHandle.HandleType.MIDDLE);
+        mDocumentOverlay.hideSelections();
+        mDocumentOverlay.hideCursor();
+        mDocumentOverlay.hideGraphicSelection();
         LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
     }
 
@@ -306,9 +306,9 @@ public class InvalidationHandler implements Document.MessageCallback {
      * Handle a transition to OverlayState.SELECTION state.
      */
     private void handleSelectionState(OverlayState previous) {
-        mTextCursorLayer.showHandle(SelectionHandle.HandleType.START);
-        mTextCursorLayer.showHandle(SelectionHandle.HandleType.END);
-        mTextCursorLayer.showSelections();
+        mDocumentOverlay.showHandle(SelectionHandle.HandleType.START);
+        mDocumentOverlay.showHandle(SelectionHandle.HandleType.END);
+        mDocumentOverlay.showSelections();
     }
 
     /**
@@ -317,8 +317,8 @@ public class InvalidationHandler implements Document.MessageCallback {
     private void handleCursorState(OverlayState previous) {
         LibreOfficeMainActivity.mAppContext.showSoftKeyboard();
         if (previous == OverlayState.TRANSITION) {
-            mTextCursorLayer.showHandle(SelectionHandle.HandleType.MIDDLE);
-            mTextCursorLayer.showCursor();
+            mDocumentOverlay.showHandle(SelectionHandle.HandleType.MIDDLE);
+            mDocumentOverlay.showCursor();
         }
     }
 
@@ -327,13 +327,13 @@ public class InvalidationHandler implements Document.MessageCallback {
      */
     private void handleTransitionState(OverlayState previous) {
         if (previous == OverlayState.SELECTION) {
-            mTextCursorLayer.hideHandle(SelectionHandle.HandleType.START);
-            mTextCursorLayer.hideHandle(SelectionHandle.HandleType.END);
-            mTextCursorLayer.hideSelections();
+            mDocumentOverlay.hideHandle(SelectionHandle.HandleType.START);
+            mDocumentOverlay.hideHandle(SelectionHandle.HandleType.END);
+            mDocumentOverlay.hideSelections();
         } else if (previous == OverlayState.CURSOR) {
-            mTextCursorLayer.hideHandle(SelectionHandle.HandleType.MIDDLE);
+            mDocumentOverlay.hideHandle(SelectionHandle.HandleType.MIDDLE);
         } else if (previous == OverlayState.GRAPHIC_SELECTION) {
-            mTextCursorLayer.hideGraphicSelection();
+            mDocumentOverlay.hideGraphicSelection();
         }
     }
 
@@ -341,7 +341,7 @@ public class InvalidationHandler implements Document.MessageCallback {
      * Handle a transition to OverlayState.GRAPHIC_SELECTION state.
      */
     private void handleGraphicSelectionState(OverlayState previous) {
-        mTextCursorLayer.showGraphicSelection();
+        mDocumentOverlay.showGraphicSelection();
         LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index c831977..61ec014 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -18,7 +18,7 @@ import android.widget.AdapterView;
 import android.widget.ListView;
 import android.widget.Toast;
 
-import org.libreoffice.overlay.TextCursorLayer;
+import org.libreoffice.overlay.DocumentOverlay;
 import org.mozilla.gecko.ZoomConstraints;
 import org.mozilla.gecko.gfx.GeckoLayerClient;
 import org.mozilla.gecko.gfx.LayerView;
@@ -52,7 +52,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
     private List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>();
     private DocumentPartViewListAdapter mDocumentPartViewListAdapter;
     private String mInputFile;
-    private TextCursorLayer mTextCursorLayer;
+    private DocumentOverlay mDocumentOverlay;
     private File mTempFile = null;
     private LOAbout mAbout;
     private ToolbarController mToolbarController;
@@ -175,7 +175,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
         mLayerClient.notifyReady();
 
         // create TextCursorLayer
-        mTextCursorLayer = new TextCursorLayer(mAppContext, layerView);
+        mDocumentOverlay = new DocumentOverlay(mAppContext, layerView);
     }
 
     private boolean copyFileToTemp() {
@@ -342,8 +342,8 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
         alertDialog.show();
     }
 
-    public TextCursorLayer getTextCursorLayer() {
-        return mTextCursorLayer;
+    public DocumentOverlay getDocumentOverlay() {
+        return mDocumentOverlay;
     }
 
     public ToolbarController getToolbarController() {
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorLayer.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
similarity index 91%
rename from android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorLayer.java
rename to android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
index 6624c66..d28f33d 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlay.java
@@ -22,19 +22,20 @@ import org.mozilla.gecko.util.FloatUtils;
 import java.util.List;
 
 /**
- * The TextCursorLayer is a layer which is responsible for showing the cursor and
- * controls its position, height and visibility.
+ * The DocumentOverlay is an overlay over the document. This class is responsible
+ * to setup the document overlay view, report visibility and position of its elements
+ * when they change and report any changes to the viewport.
  */
-public class TextCursorLayer extends Layer {
-    private static final String LOGTAG = TextCursorLayer.class.getSimpleName();
+public class DocumentOverlay extends Layer {
+    private static final String LOGTAG = DocumentOverlay.class.getSimpleName();
 
-    private final TextCursorView mCursorView;
+    private final DocumentOverlayView mCursorView;
     private float mViewLeft;
     private float mViewTop;
     private float mViewZoom;
 
-    public TextCursorLayer(Activity context, LayerView layerView) {
-        mCursorView = (TextCursorView) context.findViewById(R.id.text_cursor_view);
+    public DocumentOverlay(Activity context, LayerView layerView) {
+        mCursorView = (DocumentOverlayView) context.findViewById(R.id.text_cursor_view);
         if (mCursorView == null) {
             Log.e(LOGTAG, "Failed to initialize TextCursorLayer - CursorView is null");
         }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlayView.java
similarity index 95%
rename from android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java
rename to android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlayView.java
index ff11dc5..7d72d3e 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/DocumentOverlayView.java
@@ -9,20 +9,15 @@
 package org.libreoffice.overlay;
 
 import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 
-import org.libreoffice.LOKitShell;
-import org.libreoffice.R;
 import org.libreoffice.canvas.Cursor;
 import org.libreoffice.canvas.GraphicSelection;
 import org.libreoffice.canvas.SelectionHandle;
@@ -37,10 +32,11 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Text cursor view responsible to show the cursor drawable on the screen.
+ * Document overlay view is responsible for showing the client drawn overlay
+ * elements like cursor, selection and graphic selection, and manipulate them.
  */
-public class TextCursorView extends View implements View.OnTouchListener {
-    private static final String LOGTAG = TextCursorView.class.getSimpleName();
+public class DocumentOverlayView extends View implements View.OnTouchListener {
+    private static final String LOGTAG = DocumentOverlayView.class.getSimpleName();
 
     private static final int CURSOR_BLINK_TIME = 500;
 
@@ -65,15 +61,15 @@ public class TextCursorView extends View implements View.OnTouchListener {
 
     private SelectionHandle mDragHandle = null;
 
-    public TextCursorView(Context context) {
+    public DocumentOverlayView(Context context) {
         super(context);
     }
 
-    public TextCursorView(Context context, AttributeSet attrs) {
+    public DocumentOverlayView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
-    public TextCursorView(Context context, AttributeSet attrs, int defStyleAttr) {
+    public DocumentOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
     }
 
commit 4fb38c6f6668badcea8c12d574e97bfc4faed671
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 8 12:55:14 2015 +0900

    android: get cursor position from TextCursorLayer/View
    
    Change-Id: I7629deb6e01ace052ac8bec70202844bc627ea85

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorLayer.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorLayer.java
index 55ebfde..6624c66 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorLayer.java
@@ -195,6 +195,10 @@ public class TextCursorLayer extends Layer {
             }
         });
     }
+
+    public RectF getCursorPosition() {
+        return mCursorView.getCursorPosition();
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java
index 4e52f6e..ff11dc5 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java
@@ -372,6 +372,10 @@ public class TextCursorView extends View implements View.OnTouchListener {
         }
         return null;
     }
+
+    public RectF getCursorPosition() {
+        return mCursor.mPosition;
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 6d9af889984cf047f4724cc6087b4b4cfda2a6c3
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 8 12:18:44 2015 +0900

    android: add Cursor class for drawing the cursor to the canvas
    
    Change-Id: I5d8191ffb3d3dd3d3ab11c757a3b7d5dc3fb2e82

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/canvas/Cursor.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/canvas/Cursor.java
new file mode 100644
index 0000000..bdb8e09
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/canvas/Cursor.java
@@ -0,0 +1,38 @@
+package org.libreoffice.canvas;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+public class Cursor extends CommonCanvasElement {
+    private static final float CURSOR_WIDTH = 2f;
+    private final Paint mCursorPaint = new Paint();
+    public RectF mPosition = new RectF();
+    public RectF mScaledPosition = new RectF();
+    public int mAlpha = 0;
+
+    public Cursor() {
+        mCursorPaint.setColor(Color.BLACK);
+        mCursorPaint.setAlpha(0xFF);
+    }
+
+    @Override
+    public boolean onHitTest(float x, float y) {
+        return false;
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        canvas.drawRect(mScaledPosition, mCursorPaint);
+    }
+
+    public void reposition(RectF rect) {
+        mScaledPosition = rect;
+        mScaledPosition.right = mScaledPosition.left + CURSOR_WIDTH;
+    }
+
+    public void cycleAlpha() {
+        mCursorPaint.setAlpha(mCursorPaint.getAlpha() == 0 ? 0xFF : 0);
+    }
+}
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java
index 44d0d51..4e52f6e 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/overlay/TextCursorView.java
@@ -23,6 +23,7 @@ import android.view.View;
 
 import org.libreoffice.LOKitShell;
 import org.libreoffice.R;
+import org.libreoffice.canvas.Cursor;
 import org.libreoffice.canvas.GraphicSelection;
 import org.libreoffice.canvas.SelectionHandle;
 import org.libreoffice.canvas.SelectionHandleEnd;
@@ -40,15 +41,10 @@ import java.util.List;
  */
 public class TextCursorView extends View implements View.OnTouchListener {
     private static final String LOGTAG = TextCursorView.class.getSimpleName();
-    private static final float CURSOR_WIDTH = 2f;
+
     private static final int CURSOR_BLINK_TIME = 500;
 
     private boolean mInitialized = false;
-    private RectF mCursorPosition = new RectF();
-    private RectF mCursorScaledPosition = new RectF();
-    private Paint mCursorPaint = new Paint();
-    private int mCursorAlpha = 0;
-    private boolean mCursorVisible;
 
     private List<RectF> mSelections = new ArrayList<RectF>();
     private List<RectF> mScaledSelections = new ArrayList<RectF>();
@@ -65,6 +61,8 @@ public class TextCursorView extends View implements View.OnTouchListener {
     private SelectionHandle mHandleStart;
     private SelectionHandle mHandleEnd;
 
+    private Cursor mCursor;
+
     private SelectionHandle mDragHandle = null;
 
     public TextCursorView(Context context) {
@@ -87,9 +85,8 @@ public class TextCursorView extends View implements View.OnTouchListener {
             setOnTouchListener(this);
             mLayerView = layerView;
 
-            mCursorPaint.setColor(Color.BLACK);
-            mCursorPaint.setAlpha(0xFF);
-            mCursorVisible = false;
+            mCursor = new Cursor();
+            mCursor.setVisible(false);
 
             mSelectionPaint.setColor(Color.BLUE);
             mSelectionPaint.setAlpha(50);
@@ -113,10 +110,10 @@ public class TextCursorView extends View implements View.OnTouchListener {
      * @param position - new position of the cursor
      */
     public void changeCursorPosition(RectF position) {
-        if (RectUtils.fuzzyEquals(mCursorPosition, position)) {
+        if (RectUtils.fuzzyEquals(mCursor.mPosition, position)) {
             return;
         }
-        mCursorPosition = position;
+        mCursor.mPosition = position;
 
         ImmutableViewportMetrics metrics = mLayerView.getViewportMetrics();
         repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
@@ -149,10 +146,10 @@ public class TextCursorView extends View implements View.OnTouchListener {
     }
 
     public void repositionWithViewport(float x, float y, float zoom) {
-        mCursorScaledPosition = convertToScreen(mCursorPosition, x, y, zoom);
-        mCursorScaledPosition.right = mCursorScaledPosition.left + CURSOR_WIDTH;
+        RectF rect = convertToScreen(mCursor.mPosition, x, y, zoom);
+        mCursor.reposition(rect);
 
-        RectF rect = convertToScreen(mHandleMiddle.mDocumentPosition, x, y, zoom);
+        rect = convertToScreen(mHandleMiddle.mDocumentPosition, x, y, zoom);
         mHandleMiddle.reposition(rect.left, rect.bottom);
 
         rect = convertToScreen(mHandleStart.mDocumentPosition, x, y, zoom);
@@ -189,9 +186,8 @@ public class TextCursorView extends View implements View.OnTouchListener {
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
 
-        if (mCursorVisible) {
-            canvas.drawRect(mCursorScaledPosition, mCursorPaint);
-        }
+        mCursor.draw(canvas);
+
         mHandleMiddle.draw(canvas);
         mHandleStart.draw(canvas);
         mHandleEnd.draw(canvas);
@@ -211,8 +207,8 @@ public class TextCursorView extends View implements View.OnTouchListener {
      */
     private Runnable cursorAnimation = new Runnable() {
         public void run() {
-            if (mCursorVisible) {
-                mCursorPaint.setAlpha(mCursorPaint.getAlpha() == 0 ? 0xFF : 0);
+            if (mCursor.isVisible()) {
+                mCursor.cycleAlpha();
                 invalidate();
             }
             postDelayed(cursorAnimation, CURSOR_BLINK_TIME);
@@ -223,8 +219,8 @@ public class TextCursorView extends View implements View.OnTouchListener {
      * Show the cursor on the view.
      */
     public void showCursor() {
-        if (!mCursorVisible) {
-            mCursorVisible = true;
+        if (!mCursor.isVisible()) {
+            mCursor.setVisible(true);
             invalidate();
         }
     }
@@ -233,8 +229,8 @@ public class TextCursorView extends View implements View.OnTouchListener {
      * Hide the cursor.
      */
     public void hideCursor() {
-        if (mCursorVisible) {
-            mCursorVisible = false;
+        if (mCursor.isVisible()) {
+            mCursor.setVisible(false);
             invalidate();
         }
     }


More information about the Libreoffice-commits mailing list