[Libreoffice-commits] core.git: Branch 'feature/tiled-editing' - 357 commits - accessibility/inc accessibility/source android/Bootstrap android/experimental android/.gitignore animations/Library_animcore.mk animations/source avmedia/source avmedia/util basctl/source basic/source bridges/source canvas/source chart2/qa chart2/source cli_ure/source comphelper/Library_comphelper.mk comphelper/source compilerplugins/clang config_host/config_cups.h.in configmgr/source configure.ac connectivity/source cppuhelper/source cui/source cui/uiconfig dbaccess/qa dbaccess/source desktop/source desktop/unx drawinglayer/source editeng/source embeddedobj/source eventattacher/source extensions/source external/poppler filter/source forms/source formula/source fpicker/source framework/inc framework/source helpcompiler/inc helpcompiler/source helpcontent2 hwpfilter/source i18npool/source idlc/source include/basegfx include/comphelper include/connectivity include/cppuhelper include/dbaccess include/drawinglayer include/ editeng include/formula include/LibreOfficeKit include/o3tl include/oox include/osl include/sal include/sax include/sfx2 include/svl include/svtools include/svx include/toolkit include/tools include/ucbhelper include/unotools include/vcl include/xmloff instsetoo_native/inc_openoffice libreofficekit/CppunitTest_libreofficekit_tiledrendering.mk libreofficekit/Library_libreofficekitgtk.mk libreofficekit/Module_libreofficekit.mk libreofficekit/qa libreofficekit/README libreofficekit/source linguistic/source lotuswordpro/source odk/source officecfg/registry oox/inc oox/source package/source pyuno/zipcore reportdesign/source sal/osl sc/inc sc/Library_scd.mk sc/Library_scfilt.mk sc/qa scripting/Library_vbaevents.mk scripting/source sc/source sc/uiconfig sc/util sd/CppunitTest_sd_import_tests.mk sdext/source sd/Library_sdd.mk sd/source sd/util sfx2/source shell/inc shell/source slideshow/source solenv/bin sot/source starmath/inc starmath/source stoc/source store/source svl/Library_svl.mk sv l/source svl/util svtools/source svx/source svx/uiconfig sw/CppunitTest_sw_tiledrendering.mk sw/inc sw/Module_sw.mk sw/qa sw/source sw/util toolkit/source tools/source ucbhelper/source UnoControls/source unoidl/source unotools/source unoxml/qa unoxml/source vcl/headless vcl/inc vcl/null vcl/opengl vcl/osx vcl/qa vcl/quartz vcl/source vcl/unx vcl/win vcl/workben winaccessibility/source wizards/com wizards/source writerfilter/source xmloff/inc xmloff/source xmlsecurity/source

Miklos Vajna vmiklos at collabora.co.uk
Mon Mar 16 01:46:28 PDT 2015


Rebased ref, commits from common ancestor:
commit 2479fae410070f0e352dc15053718c88e7eca6d1
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 18:21:30 2015 +0100

    android: add toolbar button to force-show the soft keyboard
    
    Change-Id: I1758f4db7b6894df66d721af77092754b0252100

diff --git a/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_format_keyboard_grey600_24dp.png b/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_format_keyboard_grey600_24dp.png
new file mode 100644
index 0000000..cfad1bed
Binary files /dev/null and b/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_format_keyboard_grey600_24dp.png differ
diff --git a/android/experimental/LOAndroid3/res/menu/main.xml b/android/experimental/LOAndroid3/res/menu/main.xml
index 52f4ebc..8670ed3 100644
--- a/android/experimental/LOAndroid3/res/menu/main.xml
+++ b/android/experimental/LOAndroid3/res/menu/main.xml
@@ -10,6 +10,12 @@
           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"
+          android:orderInCategory="100"
+          app:showAsAction="always"/>
+
     <item android:id="@+id/action_about"
         android:title="@string/action_about"
         android:orderInCategory="100" />
diff --git a/android/experimental/LOAndroid3/res/values/strings.xml b/android/experimental/LOAndroid3/res/values/strings.xml
index e2c6ffc..3d8c3aa 100644
--- a/android/experimental/LOAndroid3/res/values/strings.xml
+++ b/android/experimental/LOAndroid3/res/values/strings.xml
@@ -35,5 +35,6 @@
     <string name="local_documents">Local documents</string>
     <string name="local_file_system">Local file system</string>
     <string name="action_bold">Bold</string>
+    <string name="action_keyboard">Show keyboard</string>
 
 </resources>
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index e1af1e2..48f7850 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -79,6 +79,9 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
             case R.id.action_bold:
                 LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Bold"));
                 return true;
+            case R.id.action_keyboard:
+                showSoftKeyboard();
+                break;
             case R.id.action_about:
                 mAbout.showAbout();
                 return true;
commit af379e99eb83fab544565d34f11f38241d0d4e8d
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 17:23:02 2015 +0100

    ImpEditView::DrawSelection: emit TEXT_SELECTION LOK callback
    
    With this, if one double-clicks on a word in an editeng text, we emit
    the correct selection rectangle list callback. No start/end rectangles
    yet, though.
    
    Change-Id: Ie05f6f4a44dc638076527f21a4b6a44e9bf63ecb

diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx
index 0c54e5e..ed456a1 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -179,6 +179,14 @@ void ImpEditView::DrawSelection( EditSelection aTmpSel, vcl::Region* pRegion, Ou
     // but someone switches the update mode!
 
     // pRegion: When not NULL, then only calculate Region.
+
+    vcl::Region aRegion;
+    if (isTiledRendering())
+    {
+        assert(!pRegion);
+        pRegion = &aRegion;
+    }
+
     tools::PolyPolygon* pPolyPoly = NULL;
     if ( pRegion )
         pPolyPoly = new tools::PolyPolygon;
@@ -313,6 +321,24 @@ void ImpEditView::DrawSelection( EditSelection aTmpSel, vcl::Region* pRegion, Ou
     if ( pRegion )
     {
         *pRegion = vcl::Region( *pPolyPoly );
+
+        if (isTiledRendering())
+        {
+            std::vector<Rectangle> aRectangles;
+            pRegion->GetRegionRectangles(aRectangles);
+            std::stringstream ss;
+
+            for (size_t i = 0; i < aRectangles.size(); ++i)
+            {
+                const Rectangle& rRectangle = aRectangles[i];
+                if (i)
+                    ss << "; ";
+                ss << rRectangle.toString().getStr();
+            }
+            OString sRectangle = ss.str().c_str();
+            libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION, sRectangle.getStr());
+        }
+
         delete pPolyPoly;
     }
     else
commit 13a06aad7c4696e0ae48bfdbdabab18eb9f81d38
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 17:07:37 2015 +0100

    SwSelPaintRects::Show: silence LOK callback till draw edit is active
    
    Change-Id: I84c1567efd2e7e6bcd09086ecce5041c2929c1b4

diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index 2e8543d..3c62a4a 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -339,7 +339,11 @@ void SwSelPaintRects::Show()
             }
         }
 
-        if (GetShell()->isTiledRendering())
+        // Tiled editing does not expose the draw and writer cursor, it just
+        // talks about "the" cursor at the moment. As long as that's true,
+        // don't say anything about the Writer cursor till a draw object is
+        // being edited.
+        if (GetShell()->isTiledRendering() && !pView->GetTextEditObject())
         {
             if (!empty())
             {
commit 30d83b0a87d93fdc2563634d666ef6ce52d333d5
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 14:50:09 2015 +0100

    Add SwXTextDocument::setTextSelection() testcase
    
    Change-Id: Id986d5408981b6ae7bf3c8c96c5226d2445a5f0d

diff --git a/libreofficekit/README b/libreofficekit/README
index 22693ce..8e32e62 100644
--- a/libreofficekit/README
+++ b/libreofficekit/README
@@ -82,7 +82,7 @@ There are currently two known LOK clients supporting tiled editing:
 
 Core has next to no idea what is the LOK client, so for effective development,
 it's recommended that the core part is developed against gtktiledviewer, and
-once a feature works there, then implement the Android part, with is slower
+once a feature works there, then implement the Android part, with its slower
 development iteration (slow uploading to the device, the need to link all
 object files into a single .so, etc).
 
diff --git a/sw/qa/extras/tiledrendering/data/set-text-selection.fodt b/sw/qa/extras/tiledrendering/data/set-text-selection.fodt
new file mode 100644
index 0000000..79a34d5
--- /dev/null
+++ b/sw/qa/extras/tiledrendering/data/set-text-selection.fodt
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oas
 is:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:
 experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+  <office:text>
+   <text:p>Aaa bbb.</text:p>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index f67f621..c5ebde7 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -22,10 +22,12 @@ class SwTiledRenderingTest : public SwModelTestBase
 {
 
 public:
+    void testSetTextSelection();
     void testSetGraphicSelection();
     void testResetSelection();
 
     CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
+    CPPUNIT_TEST(testSetTextSelection);
     CPPUNIT_TEST(testSetGraphicSelection);
     CPPUNIT_TEST(testResetSelection);
     CPPUNIT_TEST_SUITE_END();
@@ -44,6 +46,26 @@ SwXTextDocument* SwTiledRenderingTest::createDoc(const char* pName)
     return pTextDocument;
 }
 
+void SwTiledRenderingTest::testSetTextSelection()
+{
+    SwXTextDocument* pXTextDocument = createDoc("set-text-selection.fodt");
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    // Move the cursor into the second word.
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 5, /*bBasicCall=*/false);
+    // Create a selection by on the word.
+    pWrtShell->SelWrd();
+    SwShellCrsr* pShellCrsr = pWrtShell->getShellCrsr(false);
+    // Did we indeed manage to select the second word?
+    CPPUNIT_ASSERT_EQUAL(OUString("bbb"), pShellCrsr->GetTxt());
+
+    // Now use setTextSelection() to move the start of the selection 1000 twips left.
+    Point aStart = pShellCrsr->GetSttPos();
+    aStart.setX(aStart.getX() - 1000);
+    pXTextDocument->setTextSelection(LOK_SETTEXTSELECTION_START, aStart.getX(), aStart.getY());
+    // The new selection must include the first word, too -- but not the ending dot.
+    CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb"), pShellCrsr->GetTxt());
+}
+
 void SwTiledRenderingTest::testSetGraphicSelection()
 {
     SwXTextDocument* pXTextDocument = createDoc("shape.fodt");
commit 8654e16f6d48fbef1efcf50f8cdd5e5385d5a919
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 12:37:30 2015 +0100

    android: also hide keyboard on graphic selection
    
    Change-Id: I597f7099405a244f54966c203483dfda22cfbcc9

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index 1ac35d9..22aeda3 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -321,6 +321,7 @@ public class InvalidationHandler implements Document.MessageCallback {
 
     private void handleGraphicSelectionState(OverlayState previous) {
         mTextCursorLayer.showGraphicSelection();
+        LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
     }
 
     public OverlayState getCurrentState() {
@@ -335,3 +336,5 @@ public class InvalidationHandler implements Document.MessageCallback {
         SELECTION
     }
 }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 6e90795d716def8936d614bace858dfb04c6e0b7
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 12:13:19 2015 +0100

    android: hide soft keyboard when scrolling
    
    Change-Id: Ia840cd68d7af7a6948ad5766b56a3dc27cb8795b

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 ddd4a0a..589bc7a 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
@@ -13,8 +13,10 @@ import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.opengl.GLES20;
+import android.util.Log;
 
 import org.libreoffice.kit.DirectBufferAllocator;
+import org.libreoffice.LibreOfficeMainActivity;
 import org.mozilla.gecko.util.FloatUtils;
 
 import java.nio.ByteBuffer;
@@ -24,6 +26,7 @@ import java.nio.FloatBuffer;
  * Draws a small rect. This is scaled to become a scrollbar.
  */
 public class ScrollbarLayer extends TileLayer {
+    private static String LOGTAG = LayerView.class.getName();
     public static final long FADE_DELAY = 500; // milliseconds before fade-out starts
     private static final float FADE_AMOUNT = 0.03f; // how much (as a percent) the scrollbar should fade per frame
 
@@ -204,6 +207,9 @@ public class ScrollbarLayer extends TileLayer {
         beginTransaction(); // called on compositor thread
         mOpacity = 1.0f;
         endTransaction();
+
+        // Scrollbar is now visible, scrolling will start: hide the soft keyboard.
+        LibreOfficeMainActivity.mAppContext.hideSoftKeyboard();
         return true;
     }
 
@@ -445,3 +451,5 @@ public class ScrollbarLayer extends TileLayer {
         return new RectF(barStart, bottom - BAR_SIZE, barEnd, bottom);
     }
 }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 2384e6ed82a05806e6234d2057563744ef112743
Author: Henry Castro <hcastro at collabora.com>
Date:   Fri Mar 13 08:31:25 2015 +0100

    sc tiled editing: EndTracking() is necessary in the tiled rendering case.
    
    Change-Id: I0fc550ed669e08787b968ec03c09c1d8ad04dd65

diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index da733b9..d48120d 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -2438,6 +2438,11 @@ void ScGridWindow::LogicMouseButtonUp(const MouseEvent& rMouseEvent)
     assert(rDoc.GetDrawLayer()->isTiledRendering());
 
     MouseButtonUp(rMouseEvent);
+
+    // sometimes MouseButtonDown captures mouse and starts tracking, and VCL
+    // will not take care of releasing that with tiled rendering
+    if (IsTracking())
+        EndTracking();
 }
 
 void ScGridWindow::FakeButtonUp()
commit fa53289f24d09d963ffec9ee9f28ca1ee8f42a1f
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 09:58:23 2015 +0100

    SwXTextDocument: add missing @see for 3 vcl::ITiledRenderable methods
    
    Change-Id: I8bd5079c1b493e6b72ee0d71445e9aaeac76bb3d

diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index 778d073..72025628 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -395,7 +395,7 @@ public:
     // ::com::sun::star::util::XCloneable
     virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone(  ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
 
-    // ITiledRenderable
+    /// @see vcl::ITiledRenderable::paintTile().
     virtual void paintTile( VirtualDevice &rDevice,
                             int nOutputWidth,
                             int nOutputHeight,
@@ -403,15 +403,11 @@ public:
                             int nTilePosY,
                             long nTileWidth,
                             long nTileHeight ) SAL_OVERRIDE;
+    /// @see vcl::ITiledRenderable::getDocumentSize().
     virtual Size getDocumentSize() SAL_OVERRIDE;
+    /// @see vcl::ITiledRenderable::initializeForTiledRendering().
     virtual void initializeForTiledRendering() SAL_OVERRIDE;
-    /**
-     * Registers a callback that will be invoked whenever the tiled renderer
-     * wants to notify the client about an event.
-     *
-     * @param pCallBack is the callback function
-     * @param pData is private data of the client that will be sent back when the callback is invoked
-     */
+    /// @see vcl::ITiledRenderable::registerCallback().
     virtual void registerCallback(LibreOfficeKitCallback pCallback, void* pData) SAL_OVERRIDE;
     /// @see vcl::ITiledRenderable::postMouseEvent().
     virtual void postMouseEvent(int nType, int nX, int nY, int nCount) SAL_OVERRIDE;
commit 6e8da9bc4eac3eef3f68b8637ff4ef306de2e962
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 09:37:17 2015 +0100

    libreofficekit: add overview of tiled editing to README
    
    Change-Id: Ie4e28f9315c9de2062d63c5eb5e9c7481c719cef

diff --git a/libreofficekit/README b/libreofficekit/README
index eb29106..22693ce 100644
--- a/libreofficekit/README
+++ b/libreofficekit/README
@@ -38,6 +38,54 @@ colourspace (further alternatives could feasibly be implemented as needed).
 Scanlines are ordered top-down (whereas LibreOffice will internally default
 to bottom-up).
 
+Tiled Editing
+-------------
+
+On top of the tiled rendering API, a set of new methods have been added to the
+lok::Document class to allow basic editing, too. Communication between the LOK
+client and LibreOffice is a two-way channel. The client can initiate an action
+by calling the above mentioned methods. The most important methods for the
+client -> LibreOffice communication are:
+
+- initializeForRendering(), expected to be called right after
+  lok::Office::documentLoad() returned a lok::Document*.
+- postKeyEvent(), expected to be called when the user provides input on the
+  (soft-)keyboard.
+- postMouseEvent(), expected to be called when the user generated a touch or
+  mouse event.
+
+In general, all coordinates are always in absolute twips (20th of a point, or:
+1" = 1440 twips). See lok::Document in LibreOfficeKit.hxx for a full list of
+methods and their documentation.
+
+The other way around (LibreOffice -> LOK client) is implemented using a
+callback. A LOK client can register a callback using the registerCallback()
+method. Whenever editing requires some action on the client side, a callback
+event is emitted. The callback types are described using the
+LibreOfficeKitCallbackType enumeration in LibreOfficeKitEnums.h, the callback
+function signature itself is provided by the LibreOfficeKitCallback typedef in
+LibreOfficeKitTypes.h. The most important callback types:
+
+- LOK_CALLBACK_INVALIDATE_TILES: drop all tiles cached on client-side that
+  intersect with the provided rectangle
+- LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR: need to set the position and/or the
+  size of the cursor
+- LOK_CALLBACK_TEXT_SELECTION: need to adjust the selection overlay provided
+  by the client as the set of rectangles describing the selection overlay
+  changed
+
+There are currently two known LOK clients supporting tiled editing:
+
+- gtktiledviewer (see below), which allows testing the LOK core implementation
+  on (desktop) Linux
+- (LibreOffice on) Android
+
+Core has next to no idea what is the LOK client, so for effective development,
+it's recommended that the core part is developed against gtktiledviewer, and
+once a feature works there, then implement the Android part, with is slower
+development iteration (slow uploading to the device, the need to link all
+object files into a single .so, etc).
+
 LibreOfficeKitGtk
 *****************
 
commit 39bf82439fe9c753a09d9d77dbcc8e387bbe2125
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Mar 13 09:14:16 2015 +0100

    LOK: extract the callback typedef to a separate LibreOfficeKitTypes.h header
    
    With this, most LO code can avoid rebuilding when touching
    LibreOfficeKit.h, something that caused a mass-rebuild earlier.
    
    Change-Id: I4880fc7ad82cc535377b2b602897e3172ffa480b

diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
index 613d25e..093aa10 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -53,7 +53,7 @@
 #include <i18nlangtag/lang.h>
 #include <rtl/ref.hxx>
 #define LOK_USE_UNSTABLE_API
-#include <LibreOfficeKit/LibreOfficeKit.h>
+#include <LibreOfficeKit/LibreOfficeKitTypes.h>
 
 #include <boost/noncopyable.hpp>
 
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 7f9a515..f10e5e3 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -12,6 +12,8 @@
 
 #include <stddef.h>
 
+#include <LibreOfficeKit/LibreOfficeKitTypes.h>
+
 #ifdef __cplusplus
 extern "C"
 {
@@ -29,10 +31,6 @@ typedef struct _LibreOfficeKitDocumentClass LibreOfficeKitDocumentClass;
 
 #define LIBREOFFICEKIT_HAS(pKit,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitClass,member,(pKit)->pClass->nSize)
 
-#ifdef LOK_USE_UNSTABLE_API
-typedef void (*LibreOfficeKitCallback)(int nType, const char* pPayload, void* pData);
-#endif // LOK_USE_UNSTABLE_API
-
 struct _LibreOfficeKit
 {
     LibreOfficeKitClass* pClass;
diff --git a/include/LibreOfficeKit/LibreOfficeKitTypes.h b/include/LibreOfficeKit/LibreOfficeKitTypes.h
new file mode 100644
index 0000000..338f8b8
--- /dev/null
+++ b/include/LibreOfficeKit/LibreOfficeKitTypes.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_TYPES_H
+#define INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_TYPES_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef LOK_USE_UNSTABLE_API
+typedef void (*LibreOfficeKitCallback)(int nType, const char* pPayload, void* pData);
+#endif // LOK_USE_UNSTABLE_API
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // INCLUDED_LIBREOFFICEKIT_LIBREOFFICEKIT_TYPES_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx
index 97bd6a2..3e70126 100644
--- a/include/editeng/editview.hxx
+++ b/include/editeng/editview.hxx
@@ -28,7 +28,7 @@
 #include <tools/gen.hxx>
 #include <vcl/cursor.hxx>
 #define LOK_USE_UNSTABLE_API
-#include <LibreOfficeKit/LibreOfficeKit.h>
+#include <LibreOfficeKit/LibreOfficeKitTypes.h>
 
 class EditEngine;
 class ImpEditEngine;
diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx
index 441183c..e1623ec 100644
--- a/include/editeng/outliner.hxx
+++ b/include/editeng/outliner.hxx
@@ -37,7 +37,7 @@
 
 #include <tools/rtti.hxx>
 #define LOK_USE_UNSTABLE_API
-#include <LibreOfficeKit/LibreOfficeKit.h>
+#include <LibreOfficeKit/LibreOfficeKitTypes.h>
 #include <vector>
 
 class OutlinerEditEng;
diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx
index 6bd75a4..5340f06 100644
--- a/include/vcl/ITiledRenderable.hxx
+++ b/include/vcl/ITiledRenderable.hxx
@@ -12,7 +12,7 @@
 #define INCLUDED_VCL_ITILEDRENDERABLE_HXX
 
 #define LOK_USE_UNSTABLE_API
-#include <LibreOfficeKit/LibreOfficeKit.h>
+#include <LibreOfficeKit/LibreOfficeKitTypes.h>
 #include <tools/gen.hxx>
 #include <vcl/virdev.hxx>
 
commit 5df6cd16a2604163ee8e19edadba48de65ba205e
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Thu Mar 12 18:16:51 2015 +0100

    android: Make the Bold button actually work - switches to typing in bold.
    
    Change-Id: I48da0f3cc918bda1cdb396b4ea72a82eddafb9a8

diff --git a/android/Bootstrap/src/org/libreoffice/kit/Document.java b/android/Bootstrap/src/org/libreoffice/kit/Document.java
index 0e0dd59..5d97656 100644
--- a/android/Bootstrap/src/org/libreoffice/kit/Document.java
+++ b/android/Bootstrap/src/org/libreoffice/kit/Document.java
@@ -133,6 +133,12 @@ public class Document {
     public native void postMouseEvent(int type, int x, int y, int count);
 
     /**
+     * Post a .uno: command to LOK
+     * @param command - the command, like ".uno:Bold"
+     */
+    public native void postUnoCommand(String command);
+
+    /**
      * Change text selection.
      * @param type - text selection type
      * @param x - x coordinate
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
index c162c22..4413a63 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
@@ -24,14 +24,15 @@ public class LOEvent implements Comparable<LOEvent> {
     public static final int SWIPE_RIGHT = 11;
     public static final int SWIPE_LEFT = 12;
     public static final int NAVIGATION_CLICK = 13;
+    public static final int UNO_COMMAND = 14;
 
     public final int mType;
     public int mPriority = 0;
-    public String mTypeString;
+    private String mTypeString;
 
     public ThumbnailCreator.ThumbnailCreationTask mTask;
     public int mPartIndex;
-    public String mFilename;
+    public String mString;
     public ComposedTileLayer mComposedTileLayer;
     public String mTouchType;
     public PointF mDocumentCoordinate;
@@ -51,8 +52,8 @@ public class LOEvent implements Comparable<LOEvent> {
 
     public LOEvent(int type, String filename) {
         mType = type;
-        mTypeString = "Filename";
-        mFilename = filename;
+        mTypeString = "String";
+        mString = filename;
     }
 
     public LOEvent(int type, int partIndex) {
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index ea7cc31..12e4899 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -178,7 +178,7 @@ public class LOKitThread extends Thread {
     private void processEvent(LOEvent event) {
         switch (event.mType) {
             case LOEvent.LOAD:
-                loadDocument(event.mFilename);
+                loadDocument(event.mString);
                 break;
             case LOEvent.CLOSE:
                 closeDocument();
@@ -216,6 +216,9 @@ public class LOKitThread extends Thread {
             case LOEvent.NAVIGATION_CLICK:
                 mInvalidationHandler.changeStateTo(InvalidationHandler.OverlayState.NONE);
                 break;
+            case LOEvent.UNO_COMMAND:
+                mTileProvider.postUnoCommand(event.mString);
+                break;
         }
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index eb8522c..9bab22b 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -359,6 +359,11 @@ public class LOKitTileProvider implements TileProvider {
         mouseButton(Document.MOUSE_BUTTON_UP, documentCoordinate, numberOfClicks);
     }
 
+    @Override
+    public void postUnoCommand(String command) {
+        mDocument.postUnoCommand(command);
+    }
+
     private void setTextSelection(int type, PointF documentCoordinate) {
         int x = (int) pixelToTwip(documentCoordinate.x, mDPI);
         int y = (int) pixelToTwip(documentCoordinate.y, mDPI);
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index c0e4810..e1af1e2 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -77,7 +77,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
         int id = item.getItemId();
         switch (id) {
             case R.id.action_bold:
-                Toast.makeText(this,"set text to bold", Toast.LENGTH_LONG).show();
+                LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Bold"));
                 return true;
             case R.id.action_about:
                 mAbout.showAbout();
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
index 9ec55ad..c30c1bb 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
@@ -91,32 +91,30 @@ public class MockTileProvider implements TileProvider {
 
     @Override
     public void sendKeyEvent(KeyEvent keyEvent) {
-
     }
 
     @Override
     public void mouseButtonDown(PointF documentCoordinate, int numberOfClicks) {
-
     }
 
     @Override
     public void mouseButtonUp(PointF documentCoordinate, int numberOfClicks) {
+    }
 
+    @Override
+    public void postUnoCommand(String command) {
     }
 
     @Override
     public void setTextSelectionStart(PointF documentCoordinate) {
-
     }
 
     @Override
     public void setTextSelectionEnd(PointF documentCoordinate) {
-
     }
 
     @Override
     public void setTextSelectionReset(PointF documentCoordinate) {
-
     }
 
     @Override
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
index 128344f..1b34be0 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
@@ -99,6 +99,13 @@ public interface TileProvider {
      */
     void mouseButtonUp(PointF documentCoordinate, int numberOfClicks);
 
+    /**
+     * Post a UNO command to LOK.
+     *
+     * @param command - the .uno: command, like ".uno:Bold"
+     */
+    void postUnoCommand(String command);
+
     void setTextSelectionStart(PointF documentCoordinate);
 
     void setTextSelectionEnd(PointF documentCoordinate);
diff --git a/desktop/source/lib/lokandroid.cxx b/desktop/source/lib/lokandroid.cxx
index b4d0e98..c23fd3f 100644
--- a/desktop/source/lib/lokandroid.cxx
+++ b/desktop/source/lib/lokandroid.cxx
@@ -284,6 +284,18 @@ extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Document_postMou
     pDocument->pClass->postMouseEvent(pDocument, type, x, y, count);
 }
 
+extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Document_postUnoCommand
+    (JNIEnv* pEnv, jobject aObject, jstring command)
+{
+    LibreOfficeKitDocument* pDocument = getHandle<LibreOfficeKitDocument>(pEnv, aObject);
+
+    const char* pCommand = pEnv->GetStringUTFChars(command, NULL);
+
+    pDocument->pClass->postUnoCommand(pDocument, pCommand);
+
+    pEnv->ReleaseStringUTFChars(command, pCommand);
+}
+
 extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Document_setTextSelection
     (JNIEnv* pEnv, jobject aObject, jint type, jint x, jint y)
 {
commit e6f7b8823af239a69bc108cce82629c03e41039a
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 12 17:21:44 2015 +0100

    lokdocview: detect click on border vs click inside graphic selection
    
    Previously there were two cases when the user clicked inside a graphic
    selection:
    
    1) If the click started at a handle, it was a resize.
    2) Otherwise it was a move.
    
    Change 2) by requiring a click on the border for move, and otherwise
    interpreting the click as a normal one.  This makes it possible to edit
    shape text with a blinking cursor.
    
    Change-Id: Ifc063790cacb3da2684f6f72eaadd86323dd3aef

diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 338b568..1f542b5 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -114,6 +114,37 @@ gboolean lcl_signalMotion(GtkWidget* /*pEventBox*/, GdkEventButton* pEvent, LOKD
     return FALSE;
 }
 
+/// Is pClick on the border of pDocView->m_aGraphicSelection?
+bool lcl_isOnBorders(LOKDocView* pDocView, GdkPoint* pClick)
+{
+    // Handles are on the corners / edges of the shape:
+    // Let aSelection be the bounding box of all handles (a bit larger than the graphic selection).
+    int nHandleWidth = pixelToTwip(pDocView->m_aGraphicHandleRects[0].width) / pDocView->fZoom;
+    int nHandleHeight = pixelToTwip(pDocView->m_aGraphicHandleRects[0].height) / pDocView->fZoom;
+    GdkRectangle aSelection;
+    aSelection.x = pDocView->m_aGraphicSelection.x - nHandleWidth / 2;
+    aSelection.y = pDocView->m_aGraphicSelection.y - nHandleHeight / 2;
+    aSelection.width = pDocView->m_aGraphicSelection.width + nHandleWidth;
+    aSelection.height = pDocView->m_aGraphicSelection.height + nHandleHeight;
+    GdkRegion* pSelection = gdk_region_rectangle(&aSelection);
+
+    // Let aInsideBorder be the shape without the handles (a bit smaller than the graphic selection).
+    GdkRectangle aInsideBorder;
+    aInsideBorder.x = pDocView->m_aGraphicSelection.x + nHandleWidth / 2;
+    aInsideBorder.y = pDocView->m_aGraphicSelection.y + nHandleHeight / 2;
+    aInsideBorder.width = pDocView->m_aGraphicSelection.width - nHandleWidth;
+    aInsideBorder.height = pDocView->m_aGraphicSelection.height - nHandleHeight;
+    GdkRegion* pInsideBorder = gdk_region_rectangle(&aInsideBorder);
+
+    // Did we click on the border?
+    gdk_region_subtract(pSelection, pInsideBorder);
+    bool bRet = gdk_region_point_in(pSelection, pClick->x, pClick->y);
+
+    gdk_region_destroy(pInsideBorder);
+    gdk_region_destroy(pSelection);
+    return bRet;
+}
+
 /// Receives a button press event.
 gboolean lcl_signalButton(GtkWidget* /*pEventBox*/, GdkEventButton* pEvent, LOKDocView* pDocView)
 {
@@ -174,8 +205,6 @@ gboolean lcl_signalButton(GtkWidget* /*pEventBox*/, GdkEventButton* pEvent, LOKD
         aClick.height = 1;
         if (pEvent->type == GDK_BUTTON_PRESS)
         {
-            GdkRectangle aClickInTwips;
-
             if (gdk_rectangle_intersect(&aClick, &pDocView->m_aHandleStartRect, NULL))
             {
                 g_info("lcl_signalButton: start of drag start handle");
@@ -209,11 +238,10 @@ gboolean lcl_signalButton(GtkWidget* /*pEventBox*/, GdkEventButton* pEvent, LOKD
                 }
             }
 
+            GdkPoint aClickInTwips;
             aClickInTwips.x = pixelToTwip(pEvent->x) / pDocView->fZoom;
             aClickInTwips.y = pixelToTwip(pEvent->y) / pDocView->fZoom;
-            aClickInTwips.width = 1;
-            aClickInTwips.height = 1;
-            if (gdk_rectangle_intersect(&aClickInTwips, &pDocView->m_aGraphicSelection, NULL))
+            if (lcl_isOnBorders(pDocView, &aClickInTwips))
             {
                 g_info("lcl_signalButton: start of drag graphic selection");
                 pDocView->m_bInDragGraphicSelection = TRUE;
commit 60256cc547a3582807b7200f1c953d7ec091cc7d
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 12 15:18:00 2015 +0100

    lokdocview: ensure that the cursor is at least 30 twips wide
    
    While Writer uses "0" for the "minimal width" case, editeng uses 2. We
    used to round up 0 to 30, do it for any value smaller than 30.
    
    Change-Id: Ib3cc7645b55881fc51f0729163cdea5eb9ca4f0a

diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index e3fd1cb..338b568 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -519,7 +519,7 @@ static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* /*pEvent*/, gp
 
     if (pDocView->m_bEdit && pDocView->m_bCursorVisible && pDocView->m_bCursorOverlayVisible && !lcl_isEmptyRectangle(&pDocView->m_aVisibleCursor))
     {
-        if (pDocView->m_aVisibleCursor.width == 0)
+        if (pDocView->m_aVisibleCursor.width < 30)
             // Set a minimal width if it would be 0.
             pDocView->m_aVisibleCursor.width = 30;
 
commit 2ba8f4d2c0e24bc356ab72e4f00e27560f471f16
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 12 15:16:50 2015 +0100

    editeng tiled rendering: emit callbacks necessary to have a blinking cursor
    
    Change-Id: I031827cbcb14242ede549ce6f65f809795075db5

diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx
index 4db1892..684e7de 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -62,6 +62,7 @@
 #include <com/sun/star/lang/Locale.hpp>
 #include <linguistic/lngprops.hxx>
 #include <vcl/settings.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
 
 #include <com/sun/star/lang/XServiceInfo.hpp>
 
@@ -394,12 +395,17 @@ void EditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor )
         if ( !pImpEditView->DoAutoScroll() )
             bGotoCursor = false;
         pImpEditView->ShowCursor( bGotoCursor, bForceVisCursor );
+
+        if (pImpEditView->isTiledRendering())
+            pImpEditView->libreOfficeKitCallback(LOK_CALLBACK_CURSOR_VISIBLE, OString::boolean(true).getStr());
     }
 }
 
 void EditView::HideCursor()
 {
     pImpEditView->GetCursor()->Hide();
+    if (pImpEditView->isTiledRendering())
+        pImpEditView->libreOfficeKitCallback(LOK_CALLBACK_CURSOR_VISIBLE, OString::boolean(false).getStr());
 }
 
 Pair EditView::Scroll( long ndX, long ndY, sal_uInt8 nRangeCheck )
diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx
index 633593b..0c54e5e 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -45,6 +45,7 @@
 #include <svtools/transfer.hxx>
 #include <sot/exchange.hxx>
 #include <sot/formats.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
@@ -873,6 +874,14 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor, sal_uInt16
 
         GetCursor()->SetSize( aCursorSz );
 
+        if (isTiledRendering())
+        {
+            const Point& rPos = GetCursor()->GetPos();
+            Rectangle aRect(rPos.getX(), rPos.getY(), rPos.getX() + GetCursor()->GetWidth(), rPos.getY() + GetCursor()->GetHeight());
+            OString sRect = aRect.toString();
+            libreOfficeKitCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, sRect.getStr());
+        }
+
         unsigned char nCursorDir = CURSOR_DIRECTION_NONE;
         if ( IsInsertMode() && !aEditSelection.HasRange() && ( pEditEngine->pImpEditEngine->HasDifferentRTLLevels( aPaM.GetNode() ) ) )
         {
commit 00b758b40a23d715e4eb1cf8f62c901cd8c41249
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Thu Mar 12 14:59:59 2015 +0100

    LOK: Implement posting of .uno: commands.
    
    Implements also Bold button as an example in the gtktiledviewer.
    
    Change-Id: I3b07d51165f28534aadbb4673f964ec10d5fc6ef

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index ee986c5..eff82b6 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -27,6 +27,7 @@
 #include <rtl/strbuf.hxx>
 #include <rtl/bootstrap.hxx>
 #include <cppuhelper/bootstrap.hxx>
+#include <comphelper/dispatchcommand.hxx>
 #include <comphelper/processfactory.hxx>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
@@ -213,6 +214,8 @@ static void doc_postMouseEvent (LibreOfficeKitDocument* pThis,
                                 int nX,
                                 int nY,
                                 int nCount);
+static void doc_postUnoCommand(LibreOfficeKitDocument* pThis,
+                               const char* pCommand);
 static void doc_setTextSelection (LibreOfficeKitDocument* pThis,
                                   int nType,
                                   int nX,
@@ -251,6 +254,7 @@ struct LibLODocument_Impl : public _LibreOfficeKitDocument
             m_pDocumentClass->registerCallback = doc_registerCallback;
             m_pDocumentClass->postKeyEvent = doc_postKeyEvent;
             m_pDocumentClass->postMouseEvent = doc_postMouseEvent;
+            m_pDocumentClass->postUnoCommand = doc_postUnoCommand;
             m_pDocumentClass->setTextSelection = doc_setTextSelection;
             m_pDocumentClass->setGraphicSelection = doc_setGraphicSelection;
             m_pDocumentClass->resetSelection = doc_resetSelection;
@@ -723,6 +727,16 @@ static void doc_postKeyEvent(LibreOfficeKitDocument* /*pThis*/, int nType, int n
 #endif
 }
 
+static void doc_postUnoCommand(LibreOfficeKitDocument* /*pThis*/, const char* pCommand)
+{
+    OUString aCommand(pCommand, strlen(pCommand), RTL_TEXTENCODING_UTF8);
+
+    if (!comphelper::dispatchCommand(aCommand))
+    {
+        gImpl->maLastExceptionMsg = "Failed to dispatch the .uno: command";
+    }
+}
+
 static void doc_postMouseEvent(LibreOfficeKitDocument* pThis, int nType, int nX, int nY, int nCount)
 {
     ITiledRenderable* pDoc = getTiledRenderable(pThis);
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index e2ad193..7f9a515 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -132,6 +132,10 @@ struct _LibreOfficeKitDocumentClass
                          int nX,
                          int nY,
                          int nCount);
+  /// @see lok::Document::postUnoCommand
+  void (*postUnoCommand)(LibreOfficeKitDocument* pThis,
+                         const char* pCommand);
+
   /// @see lok::Document::setTextSelection
   void (*setTextSelection)(LibreOfficeKitDocument* pThis,
                          int nType,
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index c19aa50..1d7d709 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -131,6 +131,16 @@ public:
     }
 
     /**
+     * Posts an UNO command to the document.
+     *
+     * @param pCommand uno command to be posted to the document, like ".uno:Bold"
+     */
+    inline void postUnoCommand(const char* pCommand)
+    {
+        mpDoc->pClass->postUnoCommand(mpDoc, pCommand);
+    }
+
+    /**
      * Sets the start or end of a text selection.
      *
      * @param nType @see LibreOfficeKitSetTextSelectionType
diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h
index 77e9118..f088f49 100644
--- a/include/LibreOfficeKit/LibreOfficeKitGtk.h
+++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h
@@ -121,6 +121,9 @@ void            lok_docview_set_edit        (LOKDocView* pDocView,
                                              gboolean bEdit);
 /// Gets if the viewer is actually an editor or not.
 gboolean        lok_docview_get_edit        (LOKDocView* pDocView);
+
+/// Posts the .uno: command to the LibreOfficeKit.
+void            lok_docview_post_command    (LOKDocView* pDocView, const char* pCommand);
 #ifdef __cplusplus
 }
 #endif
diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
index 32a107e..92ffdd4 100644
--- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
@@ -35,6 +35,7 @@ static int help()
 
 static GtkWidget* pDocView;
 static GtkToolItem* pEnableEditing;
+static GtkToolItem* pBold;
 static GtkWidget* pDocViewQuad;
 static GtkWidget* pVBox;
 // GtkComboBox requires gtk 2.24 or later
@@ -124,6 +125,14 @@ static void signalEdit(LOKDocView* pLOKDocView, gboolean bWasEdit, gpointer /*pD
         gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(pEnableEditing), bEdit);
 }
 
+/// User clicked on the 'Bold' button -> inform LOKDocView.
+void toggleBold(GtkWidget* /*pButton*/, gpointer /*pItem*/)
+{
+    LOKDocView* pLOKDocView = LOK_DOCVIEW(pDocView);
+
+    lok_docview_post_command(pLOKDocView, ".uno:Bold");
+}
+
 void changeQuadView( GtkWidget* /*pButton*/, gpointer /* pItem */ )
 {
     if ( pDocView )
@@ -364,6 +373,12 @@ int main( int argc, char* argv[] )
     gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), pEnableEditing, -1);
     g_signal_connect(G_OBJECT(pEnableEditing), "toggled", G_CALLBACK(toggleEditing), NULL);
 
+    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), gtk_separator_tool_item_new(), -1);
+    pBold = gtk_toggle_tool_button_new();
+    gtk_tool_button_set_label(GTK_TOOL_BUTTON(pBold), "Bold");
+    gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), pBold, -1);
+    g_signal_connect(G_OBJECT(pBold), "toggled", G_CALLBACK(toggleBold), NULL);
+
     gtk_box_pack_start( GTK_BOX(pVBox), pToolbar, FALSE, FALSE, 0 ); // Adds to top.
 
     // Docview
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 8349256..e3fd1cb 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -971,4 +971,9 @@ SAL_DLLPUBLIC_EXPORT gboolean lok_docview_get_edit(LOKDocView* pDocView)
     return pDocView->m_bEdit;
 }
 
+SAL_DLLPUBLIC_EXPORT void lok_docview_post_command(LOKDocView* pDocView, const char* pCommand)
+{
+    pDocView->pDocument->pClass->postUnoCommand(pDocView->pDocument, pCommand);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit a250e9d3ecf899796e7cfbdd2266e494353580c0
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Thu Mar 12 14:04:31 2015 +0100

    Factor out the .uno: command dispatching to a separate function / file.
    
    Change-Id: I8486933d57d42992e66be7f17443320cfc2ad629

diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index 7a263c9..e36fe31 100644
--- a/comphelper/Library_comphelper.mk
+++ b/comphelper/Library_comphelper.mk
@@ -82,6 +82,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\
     comphelper/source/misc/componentmodule \
     comphelper/source/misc/configuration \
     comphelper/source/misc/configurationhelper \
+    comphelper/source/misc/dispatchcommand \
     comphelper/source/misc/docpasswordhelper \
     comphelper/source/misc/docpasswordrequest \
     comphelper/source/misc/documentinfo \
diff --git a/comphelper/source/misc/dispatchcommand.cxx b/comphelper/source/misc/dispatchcommand.cxx
new file mode 100644
index 0000000..dd43523
--- /dev/null
+++ b/comphelper/source/misc/dispatchcommand.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/dispatchcommand.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+
+using namespace css;
+
+namespace comphelper {
+
+bool dispatchCommand(const OUString& rCommand)
+{
+    // Target where we will execute the .uno: command
+    uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
+    uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(xContext);
+
+    uno::Reference<frame::XFrame> xFrame(xDesktop->getActiveFrame());
+    if (!xFrame.is())
+        xFrame = uno::Reference<frame::XFrame>(xDesktop, uno::UNO_QUERY);
+
+    uno::Reference<frame::XDispatchProvider> xDispatchProvider(xFrame, uno::UNO_QUERY);
+    if (!xDispatchProvider.is())
+        return false;
+
+    util::URL aCommandURL;
+    aCommandURL.Complete = rCommand;
+    uno::Reference<util::XURLTransformer> xParser = util::URLTransformer::create(xContext);
+    xParser->parseStrict(aCommandURL);
+
+    uno::Reference<frame::XDispatch> xDisp = xDispatchProvider->queryDispatch(aCommandURL, OUString(), 0);
+    if (!xDisp.is())
+        return false;
+
+    // And do the work...
+    xDisp->dispatch(aCommandURL, uno::Sequence<beans::PropertyValue>());
+
+    return true;
+}
+
+} // namespace comphelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/comphelper/dispatchcommand.hxx b/include/comphelper/dispatchcommand.hxx
new file mode 100644
index 0000000..7289dd7
--- /dev/null
+++ b/include/comphelper/dispatchcommand.hxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_COMPHELPER_DISPATCHCOMMAND_HXX
+#define INCLUDED_COMPHELPER_DISPATCHCOMMAND_HXX
+
+#include <comphelper/comphelperdllapi.h>
+#include <rtl/ustring.hxx>
+
+namespace comphelper
+{
+
+/** Dispatch the given UNO command in the active frame.
+
+    @param rCommand the command to dispatch, like ".uno:Bold".
+
+    @return true on success.
+*/
+COMPHELPER_DLLPUBLIC bool dispatchCommand(const OUString& rCommand);
+
+}
+
+#endif // INCLUDED_COMPHELPER_DISPATCHCOMMAND_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index be4b464..ec9b9a0 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -41,13 +41,7 @@
 #include <window.h>
 #include <controldata.hxx>
 
-#include <comphelper/processfactory.hxx>
-
-#include <com/sun/star/frame/Desktop.hpp>
-#include <com/sun/star/frame/XDispatch.hpp>
-#include <com/sun/star/frame/XDispatchProvider.hpp>
-#include <com/sun/star/util/URL.hpp>
-#include <com/sun/star/util/URLTransformer.hpp>
+#include <comphelper/dispatchcommand.hxx>
 
 using namespace css;
 
@@ -605,35 +599,12 @@ sal_IntPtr Button::dispatchCommandHandler(void *, void *pCaller)
     if (pButton == NULL)
         return 0;
 
-    // Target where we will execute the .uno: command
-    uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
-    uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(xContext);
-
-    uno::Reference<frame::XFrame> xFrame(xDesktop->getActiveFrame());
-    if (!xFrame.is())
-        xFrame = uno::Reference<frame::XFrame>(xDesktop, uno::UNO_QUERY);
-
-    uno::Reference<frame::XDispatchProvider> xDispatchProvider(xFrame, uno::UNO_QUERY);
-    if (!xDispatchProvider.is())
+    if (!comphelper::dispatchCommand(pButton->maCommand))
         return 0;
 
-    util::URL aCommandURL;
-    aCommandURL.Complete = pButton->maCommand;
-    uno::Reference<util::XURLTransformer> xParser = util::URLTransformer::create(xContext);
-    xParser->parseStrict(aCommandURL);
-
-    uno::Reference<frame::XDispatch> xDisp = xDispatchProvider->queryDispatch(aCommandURL, OUString(), 0);
-    if (!xDisp.is())
-        return 0;
-
-    // And do the work...
-    xDisp->dispatch(aCommandURL, uno::Sequence<beans::PropertyValue>());
-
     return 1;
 }
 
-
-
 void PushButton::ImplInitPushButtonData()
 {
     mpWindowImpl->mbPushButton    = true;
commit 4a8afa003b854e74807389c8f82fd4609485f1b8
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 12 13:08:49 2015 +0100

    Add ImpEditView::libreOfficeKitCallback()
    
    And various other methods, so that it's possible to invoke the callback
    in ImpEditView. This will be needed by the blinking editeng cursor.
    
    Change-Id: Ie1b6957e5c48f606e71d5808df3f632924d3a2ec

diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx
index cfd4fc5..4db1892 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -582,6 +582,11 @@ bool EditView::isTiledRendering()
     return pImpEditView->isTiledRendering();
 }
 
+void EditView::registerLibreOfficeKitCallback(LibreOfficeKitCallback pCallback, void* pLibreOfficeKitData)
+{
+    pImpEditView->registerLibreOfficeKitCallback(pCallback, pLibreOfficeKitData);
+}
+
 void EditView::SetControlWord( sal_uInt32 nWord )
 {
     pImpEditView->nControl = nWord;
diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx
index ed543cb..633593b 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -76,6 +76,8 @@ ImpEditView::ImpEditView( EditView* pView, EditEngine* pEng, vcl::Window* pWindo
     pPointer            = NULL;
     pBackgroundColor    = NULL;
     mbTiledRendering    = false;
+    mpLibreOfficeKitCallback = 0;
+    mpLibreOfficeKitData = 0;
     nScrollDiffX        = 0;
     nExtraCursorFlags   = 0;
     nCursorBidiLevel    = CURSOR_BIDILEVEL_DONTKNOW;
@@ -123,6 +125,18 @@ bool ImpEditView::isTiledRendering() const
     return mbTiledRendering;
 }
 
+void ImpEditView::registerLibreOfficeKitCallback(LibreOfficeKitCallback pCallback, void* pData)
+{
+    mpLibreOfficeKitCallback = pCallback;
+    mpLibreOfficeKitData = pData;
+}
+
+void ImpEditView::libreOfficeKitCallback(int nType, const char* pPayload) const
+{
+    if (mpLibreOfficeKitCallback)
+        mpLibreOfficeKitCallback(nType, pPayload, mpLibreOfficeKitData);
+}
+
 void ImpEditView::SetEditSelection( const EditSelection& rEditSelection )
 {
     // set state before notification
diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
index 5ec289b..613d25e 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -52,6 +52,8 @@
 
 #include <i18nlangtag/lang.h>
 #include <rtl/ref.hxx>
+#define LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKit.h>
 
 #include <boost/noncopyable.hpp>
 
@@ -217,6 +219,8 @@ private:
     vcl::Cursor*        pCursor;
     Color*              pBackgroundColor;
     bool                mbTiledRendering;
+    LibreOfficeKitCallback mpLibreOfficeKitCallback;
+    void* mpLibreOfficeKitData;
     EditEngine*         pEditEngine;
     vcl::Window*             pOutWin;
     Pointer*            pPointer;
@@ -367,6 +371,10 @@ public:
 
     void            setTiledRendering(bool bTiledRendering);
     bool            isTiledRendering() const;
+    /// @see vcl::ITiledRenderable::registerCallback().
+    void registerLibreOfficeKitCallback(LibreOfficeKitCallback pCallback, void* pLibreOfficeKitData);
+    /// Invokes the registered callback, if there are any.
+    void libreOfficeKitCallback(int nType, const char* pPayload) const;
 
     bool        IsWrongSpelledWord( const EditPaM& rPaM, bool bMarkIfWrong );
     OUString        SpellIgnoreOrAddWord( bool bAdd );
diff --git a/editeng/source/outliner/outlvw.cxx b/editeng/source/outliner/outlvw.cxx
index 9e61056..bd2b084 100644
--- a/editeng/source/outliner/outlvw.cxx
+++ b/editeng/source/outliner/outlvw.cxx
@@ -1425,6 +1425,11 @@ void OutlinerView::setTiledRendering(bool bTiledRendering)
     pEditView->setTiledRendering(bTiledRendering);
 }
 
+void OutlinerView::registerLibreOfficeKitCallback(LibreOfficeKitCallback pCallback, void* pLibreOfficeKitData)
+{
+    pEditView->registerLibreOfficeKitCallback(pCallback, pLibreOfficeKitData);
+}
+
 Color OutlinerView::GetBackgroundColor()
 {
     return pEditView->GetBackgroundColor();
diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx
index 439f63b..97bd6a2 100644
--- a/include/editeng/editview.hxx
+++ b/include/editeng/editview.hxx
@@ -27,6 +27,8 @@
 #include <tools/color.hxx>
 #include <tools/gen.hxx>
 #include <vcl/cursor.hxx>
+#define LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKit.h>
 
 class EditEngine;
 class ImpEditEngine;
@@ -171,6 +173,8 @@ public:
 
     void            setTiledRendering(bool bTiledRendering);
     bool            isTiledRendering();
+    /// @see vcl::ITiledRenderable::registerCallback().
+    void registerLibreOfficeKitCallback(LibreOfficeKitCallback pCallback, void* pLibreOfficeKitData);
 
     void            SetControlWord( sal_uInt32 nWord );
     sal_uInt32      GetControlWord() const;
diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx
index ce25da0..441183c 100644
--- a/include/editeng/outliner.hxx
+++ b/include/editeng/outliner.hxx
@@ -36,6 +36,8 @@
 #include <svtools/grfmgr.hxx>
 
 #include <tools/rtti.hxx>
+#define LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKit.h>
 #include <vector>
 
 class OutlinerEditEng;
@@ -268,6 +270,8 @@ public:
 
     /// Set if we are doing tiled rendering.
     void        setTiledRendering(bool bTiledRendering);
+    /// @see vcl::ITiledRenderable::registerCallback().
+    void registerLibreOfficeKitCallback(LibreOfficeKitCallback pCallback, void* pLibreOfficeKitData);
 
     SfxItemSet  GetAttribs();
 
diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx
index 8cd4541..3f61550 100644
--- a/include/svx/svdmodel.hxx
+++ b/include/svx/svdmodel.hxx
@@ -343,6 +343,10 @@ public:
     bool isTiledRendering() const;
     /// The actual implementation of the vcl::ITiledRenderable::registerCallback() API.
     void registerLibreOfficeKitCallback(LibreOfficeKitCallback pCallback, void* pLibreOfficeKitData);
+    /// Gets the LOK callback registered by registerLibreOfficeKitCallback().
+    LibreOfficeKitCallback getLibreOfficeKitCallback() const;
+    /// Gets the LOK data registered by registerLibreOfficeKitCallback().
+    void* getLibreOfficeKitData() const;
     /// Invokes the registered callback, if there are any.
     void libreOfficeKitCallback(int nType, const char* pPayload) const;
     // If a new MapMode is set on the RefDevice (or similar)
diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx
index 0625696..5cf1ca1 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -447,6 +447,7 @@ OutlinerView* SdrObjEditView::ImpMakeOutlinerView(vcl::Window* pWin, bool /*bNoP
     pOutlView->SetControlWord(nStat);
     pOutlView->SetBackgroundColor( aBackground );
     pOutlView->setTiledRendering(GetModel()->isTiledRendering());
+    pOutlView->registerLibreOfficeKitCallback(GetModel()->getLibreOfficeKitCallback(), GetModel()->getLibreOfficeKitData());
     if (pText!=NULL)
     {
         pOutlView->SetAnchorMode((EVAnchorMode)(pText->GetOutlinerViewAnchorMode()));
diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx
index 66f004e..9e59338 100644
--- a/svx/source/svdraw/svdmodel.cxx
+++ b/svx/source/svdraw/svdmodel.cxx
@@ -820,6 +820,16 @@ void SdrModel::libreOfficeKitCallback(int nType, const char* pPayload) const
         mpLibreOfficeKitCallback(nType, pPayload, mpLibreOfficeKitData);
 }
 
+LibreOfficeKitCallback SdrModel::getLibreOfficeKitCallback() const
+{
+    return mpLibreOfficeKitCallback;
+}
+
+void* SdrModel::getLibreOfficeKitData() const
+{
+    return mpLibreOfficeKitData;
+}
+
 void SdrModel::ImpReformatAllTextObjects()
 {
     if( isLocked() )
commit 5666552a07c0f742087cf987679ffeb5fa99b1a4
Author: Henry Castro <hcastro at collabora.com>
Date:   Thu Mar 12 11:34:35 2015 +0100

    sc tiled rendering: Avoid warnings about a non-existing SdrPaintWindow.
    
    Change-Id: Idb9695515d9a829fb63ea37e02f4bf2b111bf6bf

diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 6f6c65a..87c3cab 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -953,7 +953,15 @@ void ScGridWindow::PaintTile( VirtualDevice& rDevice,
             -fTilePosXPixel, -fTilePosYPixel, nCol1, nRow1, nCol2, nRow2,
             fPPTX, fPPTY);
 
+    // create a temporary SdrPaintWindow to avoid warnings
+    SdrPaintWindow aTemporaryPaintWindow(*pViewData->GetScDrawView(), rDevice);
+    SdrPageView* pSdrPageView = pViewData->GetScDrawView()->GetSdrPageView();
+    pSdrPageView->AddPaintWindowToPageView(aTemporaryPaintWindow);
+
+    // draw the content
     DrawContent(rDevice, aTabInfo, aOutputData, true, SC_UPDATE_ALL);
+
+    pSdrPageView->RemovePaintWindowFromPageView(aTemporaryPaintWindow);
 }
 
 void ScGridWindow::LogicInvalidate(const ::vcl::Region* pRegion)
commit ab27a77aa82bd0bcad59652b76a5c65e5e946cea
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 12 10:18:48 2015 +0100

    Add SwXTextDocument::setGraphicSelection() testcase
    
    Change-Id: I172ef9f5cfdae8cbff88419171c5b8ad55fb194c

diff --git a/sw/qa/extras/tiledrendering/data/reset-selection.fodt b/sw/qa/extras/tiledrendering/data/shape.fodt
similarity index 100%
rename from sw/qa/extras/tiledrendering/data/reset-selection.fodt
rename to sw/qa/extras/tiledrendering/data/shape.fodt
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index de23c69..f67f621 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -8,6 +8,7 @@
  */
 
 #include <swmodeltestbase.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <svx/svdpage.hxx>
 #include <svx/svdview.hxx>
 #include <crsskip.hxx>
@@ -21,9 +22,11 @@ class SwTiledRenderingTest : public SwModelTestBase
 {
 
 public:
+    void testSetGraphicSelection();
     void testResetSelection();
 
     CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
+    CPPUNIT_TEST(testSetGraphicSelection);
     CPPUNIT_TEST(testResetSelection);
     CPPUNIT_TEST_SUITE_END();
 
@@ -37,12 +40,35 @@ SwXTextDocument* SwTiledRenderingTest::createDoc(const char* pName)
 
     SwXTextDocument* pTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
     CPPUNIT_ASSERT(pTextDocument);
+    pTextDocument->initializeForTiledRendering();
     return pTextDocument;
 }
 
+void SwTiledRenderingTest::testSetGraphicSelection()
+{
+    SwXTextDocument* pXTextDocument = createDoc("shape.fodt");
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+    SdrObject* pObject = pPage->GetObj(0);
+    pWrtShell->SelectObj(Point(), 0, pObject);
+    // Make sure the rectangle has 8 handles: at each corner and at the center of each edge.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(8), pObject->GetHdlCount());
+    // Take the bottom center one.
+    SdrHdl* pHdl = pObject->GetHdl(6);
+    CPPUNIT_ASSERT_EQUAL(HDL_LOWER, pHdl->GetKind());
+    Rectangle aShapeBefore = pObject->GetSnapRect();
+    // Resize.
+    pXTextDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, pHdl->GetPos().getX(), pHdl->GetPos().getY());
+    pXTextDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, pHdl->GetPos().getX(), pHdl->GetPos().getY() + 1000);
+    Rectangle aShapeAfter = pObject->GetSnapRect();
+    // Check that a resize happened, but aspect ratio is not kept.
+    CPPUNIT_ASSERT_EQUAL(aShapeBefore.getWidth(), aShapeAfter.getWidth());
+    CPPUNIT_ASSERT_EQUAL(aShapeBefore.getHeight() + 1000, aShapeAfter.getHeight());
+}
+
 void SwTiledRenderingTest::testResetSelection()
 {
-    SwXTextDocument* pXTextDocument = createDoc("reset-selection.fodt");
+    SwXTextDocument* pXTextDocument = createDoc("shape.fodt");
     SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
     // Select one character.
     pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false);
commit a1ae91f00fd909a2ba31bb08116baf84f9881a36
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Mar 11 18:00:26 2015 +0100

    Add testcase for SwXTextDocument::resetSelection().
    
    Change-Id: Idc97ebfe3db27ac52c1c6b16177f08118a750e69

diff --git a/sw/CppunitTest_sw_tiledrendering.mk b/sw/CppunitTest_sw_tiledrendering.mk
new file mode 100644
index 0000000..be7986b
--- /dev/null
+++ b/sw/CppunitTest_sw_tiledrendering.mk
@@ -0,0 +1,62 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,sw_tiledrendering))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,sw_tiledrendering, \
+    sw/qa/extras/tiledrendering/tiledrendering \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,sw_tiledrendering, \
+    comphelper \
+    cppu \
+    cppuhelper \
+    editeng \
+    sal \
+    sfx \
+    svl \
+    svt \
+	svxcore \
+    sw \
+    test \
+    unotest \
+    vcl \
+    tl \
+	utl \
+    $(gb_UWINAPI) \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,sw_tiledrendering,\
+    boost_headers \
+    libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_set_include,sw_tiledrendering,\
+    -I$(SRCDIR)/sw/inc \
+    -I$(SRCDIR)/sw/source/core/inc \
+    -I$(SRCDIR)/sw/source/uibase/inc \
+    -I$(SRCDIR)/sw/qa/extras/inc \
+    $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,sw_tiledrendering,\
+    offapi \
+    udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,sw_tiledrendering))
+$(eval $(call gb_CppunitTest_use_vcl,sw_tiledrendering))
+
+$(eval $(call gb_CppunitTest_use_rdb,sw_tiledrendering,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,sw_tiledrendering))
+
+# vim: set noet sw=4 ts=4:
diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk
index d15c5b5..78a45e1 100644
--- a/sw/Module_sw.mk
+++ b/sw/Module_sw.mk
@@ -70,6 +70,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sw,\
     CppunitTest_sw_odfexport \
     CppunitTest_sw_odfimport \
     CppunitTest_sw_uiwriter \
+    CppunitTest_sw_tiledrendering \
     CppunitTest_sw_mailmerge \
     CppunitTest_sw_globalfilter \
 ))
diff --git a/sw/qa/extras/tiledrendering/data/reset-selection.fodt b/sw/qa/extras/tiledrendering/data/reset-selection.fodt
new file mode 100644
index 0000000..feefe48
--- /dev/null
+++ b/sw/qa/extras/tiledrendering/data/reset-selection.fodt
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oas
 is:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:
 experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+  <office:text>
+   <text:sequence-decls>
+    <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+   </text:sequence-decls>
+   <text:p><draw:custom-shape text:anchor-type="paragraph" draw:z-index="0" svg:width="4.883cm" svg:height="3.225cm" svg:x="2.602cm" svg:y="1.178cm">
+     <text:p/>
+     <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:glue-points="10800 0 3163 3163 0 10800 3163 18437 10800 21600 18437 18437 21600 10800 18437 3163" draw:text-areas="3163 3163 18437 18437" draw:type="ellipse" draw:enhanced-path="U 10800 10800 10800 10800 0 360 Z N"/>
+    </draw:custom-shape>Hello.</text:p>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
new file mode 100644
index 0000000..de23c69
--- /dev/null
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <swmodeltestbase.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdview.hxx>
+#include <crsskip.hxx>
+#include <drawdoc.hxx>
+#include <wrtsh.hxx>
+
+static const char* DATA_DIRECTORY = "/sw/qa/extras/tiledrendering/data/";
+
+/// Testsuite for the SwXTextDocument methods implementing the vcl::ITiledRenderable interface.
+class SwTiledRenderingTest : public SwModelTestBase
+{
+
+public:
+    void testResetSelection();
+
+    CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
+    CPPUNIT_TEST(testResetSelection);
+    CPPUNIT_TEST_SUITE_END();
+
+private:
+    SwXTextDocument* createDoc(const char* pName);
+};
+
+SwXTextDocument* SwTiledRenderingTest::createDoc(const char* pName)
+{
+    load(DATA_DIRECTORY, pName);
+
+    SwXTextDocument* pTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDocument);
+    return pTextDocument;
+}
+
+void SwTiledRenderingTest::testResetSelection()
+{
+    SwXTextDocument* pXTextDocument = createDoc("reset-selection.fodt");
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    // Select one character.
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false);
+    SwShellCrsr* pShellCrsr = pWrtShell->getShellCrsr(false);
+    // We have a text selection.
+    CPPUNIT_ASSERT(pShellCrsr->HasMark());
+
+    pXTextDocument->resetSelection();
+    // We no longer have a text selection.
+    CPPUNIT_ASSERT(!pShellCrsr->HasMark());
+
+    SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+    SdrObject* pObject = pPage->GetObj(0);
+    Point aPoint = pObject->GetSnapRect().Center();
+    // Select the shape.
+    pWrtShell->EnterSelFrmMode(&aPoint);
+    // We have a graphic selection.
+    CPPUNIT_ASSERT(pWrtShell->IsSelFrmMode());
+
+    pXTextDocument->resetSelection();
+    // We no longer have a graphic selection.
+    CPPUNIT_ASSERT(!pWrtShell->IsSelFrmMode());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 73ed546f98f97024b48f9040825a3a32e71ac8dd
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Mar 11 16:33:25 2015 +0100

    SdrMarkView::SetMarkHandles: when tiled rendering, show non-frame handles, too
    
    This gives graphic selection / moving / resizing for non-frame shapes
    (the ones with the blue handles on the desktop).
    
    Change-Id: I59018d4beb2ad1d2133d439afda56686b3c00b0c

diff --git a/svx/source/svdraw/svdmrkv.cxx b/svx/source/svdraw/svdmrkv.cxx
index 3209f4e..cc8badb 100644
--- a/svx/source/svdraw/svdmrkv.cxx
+++ b/svx/source/svdraw/svdmrkv.cxx
@@ -699,20 +699,20 @@ void SdrMarkView::SetMarkHandles()
             }
         }
 
-        if (bFrmHdl)
-        {
-            Rectangle aRect(GetMarkedObjRect());
+        Rectangle aRect(GetMarkedObjRect());
 
-            if (GetModel()->isTiledRendering())
-            {
-                OString sRectangle;
-                if (aRect.IsEmpty())
-                    sRectangle = "EMPTY";
-                else
-                    sRectangle = aRect.toString();
-                GetModel()->libreOfficeKitCallback(LOK_CALLBACK_GRAPHIC_SELECTION, sRectangle.getStr());
-            }
+        if (GetModel()->isTiledRendering())
+        {
+            OString sRectangle;
+            if (aRect.IsEmpty())
+                sRectangle = "EMPTY";
+            else
+                sRectangle = aRect.toString();
+            GetModel()->libreOfficeKitCallback(LOK_CALLBACK_GRAPHIC_SELECTION, sRectangle.getStr());
+        }
 
+        if (bFrmHdl)
+        {
             if(!aRect.IsEmpty())
             { // otherwise nothing is found
                 if( bSingleTextObjMark )
commit ea607240291126b4c9eb73dadcb83ede560eb080
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Wed Mar 11 11:14:07 2015 +0100

    Small cleanup - no need to have 2 OpenURL's.
    
    Change-Id: Ib76729004f36e087aaf5a6089a60675c606e9070

diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index 6b03dc4b..f8555b4 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -575,9 +575,9 @@ public:
     SC_DLLPUBLIC static ScUserList*         GetUserList();
     static void                 SetUserList( const ScUserList* pNewList );
     SC_DLLPUBLIC static const OUString&       GetRscString( sal_uInt16 nIndex );
-    static void                 OpenURL( const OUString& rURL, const OUString& rTarget );
-    // Check if tiled-rendering, and leave clients to handle the openURL action if that's the case, OpenURL otherwise.
-    static void                 OpenURL( const SdrModel* pDrawLayer, const OUString& rURL, const OUString& rTarget );
+    /// Open the specified URL.
+    /// If pDrawLayer is specified, check if tiled-rendering, and leave clients to handle the openURL action if that's the case.
+    static void                 OpenURL(const OUString& rURL, const OUString& rTarget, const SdrModel* pDrawLayer = NULL);
     SC_DLLPUBLIC static OUString            GetAbsDocName( const OUString& rFileName,
                                                 SfxObjectShell* pShell );
     SC_DLLPUBLIC static OUString            GetDocTabName( const OUString& rFileName,
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
index 81b28d5..d71154d 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -867,18 +867,14 @@ bool ScGlobal::EETextObjEqual( const EditTextObject* pObj1,
     return false;
 }
 
-
-void ScGlobal::OpenURL( const SdrModel* pDrawLayer, const OUString& rURL, const OUString& rTarget ) {
-    if (pDrawLayer && pDrawLayer->isTiledRendering()) {
-            pDrawLayer->libreOfficeKitCallback(LOK_CALLBACK_HYPERLINK_CLICKED, rURL.toUtf8().getStr());
-            return;
+void ScGlobal::OpenURL(const OUString& rURL, const OUString& rTarget, const SdrModel* pDrawLayer)
+{
+    if (pDrawLayer && pDrawLayer->isTiledRendering())
+    {
+        pDrawLayer->libreOfficeKitCallback(LOK_CALLBACK_HYPERLINK_CLICKED, rURL.toUtf8().getStr());
+        return;
     }
-    // Proceed to openURL if not tiled rendering.
-    OpenURL(rURL, rTarget);
-}
 
-void ScGlobal::OpenURL( const OUString& rURL, const OUString& rTarget )
-{
     // OpenURL is always called in the GridWindow by mouse clicks in some way or another.
     // That's why pScActiveViewShell and nScClickMouseModifier are correct.
     // SvtSecurityOptions to access Libreoffice global security parameters
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 3063bdf..da733b9 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -2295,7 +2295,7 @@ void ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
             // ScGlobal::OpenURL() only understands Calc A1 style syntax.
             // Convert it to Calc A1 before calling OpenURL().
             if (pDoc->GetAddressConvention() == formula::FormulaGrammar::CONV_OOO)
-                ScGlobal::OpenURL(pViewData->GetDocument()->GetDrawLayer(), aUrl, aTarget);
+                ScGlobal::OpenURL(aUrl, aTarget, pViewData->GetDocument()->GetDrawLayer());
             else
             {
                 ScAddress aTempAddr;
diff --git a/sd/source/ui/func/fusel.cxx b/sd/source/ui/func/fusel.cxx
index 1ace237..0cb164d 100644
--- a/sd/source/ui/func/fusel.cxx
+++ b/sd/source/ui/func/fusel.cxx
@@ -269,7 +269,8 @@ bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
                 mpWindow->ReleaseMouse();
 
                 // If tiled rendering, let client handles URL execution and early returns.
-                if (mpDoc->isTiledRendering()) {
+                if (mpDoc->isTiledRendering())
+                {
                     mpDoc->libreOfficeKitCallback(LOK_CALLBACK_HYPERLINK_CLICKED,
                             aVEvt.pURLField->GetURL().toUtf8().getStr());
                     return true;
commit bd3771e1057ae90875d312faa4c30645627260e3
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Mar 11 17:24:49 2015 +0900

    android: add to JNI - setGraphicSelection, resetSelection
    
    Change-Id: Ib81763148b077423d3903802b13a11b15ba3b0c1

diff --git a/android/Bootstrap/src/org/libreoffice/kit/Document.java b/android/Bootstrap/src/org/libreoffice/kit/Document.java
index 9ebfdfc..0e0dd59 100644
--- a/android/Bootstrap/src/org/libreoffice/kit/Document.java
+++ b/android/Bootstrap/src/org/libreoffice/kit/Document.java
@@ -50,6 +50,12 @@ public class Document {
     public static final int SET_TEXT_SELECTION_END = 1;
     public static final int SET_TEXT_SELECTION_RESET = 2;
 
+    /**
+     * Set graphic selection types
+     */
+    public static final int SET_GRAPHIC_SELECTION_START = 0;
+    public static final int SET_GRAPHIC_SELECTION_END = 1;
+
     private final ByteBuffer handle;
     private MessageCallback messageCallback = null;
 
@@ -127,7 +133,7 @@ public class Document {
     public native void postMouseEvent(int type, int x, int y, int count);
 
     /**
-     * Change text selection
+     * Change text selection.
      * @param type - text selection type
      * @param x - x coordinate
      * @param y - y coordinate
@@ -135,6 +141,19 @@ public class Document {
     public native void setTextSelection(int type, int x, int y);
 
     /**
+     * Change graphic selection.
+     * @param type - graphic selection type
+     * @param x - x coordinate
+     * @param y - y coordinate
+     */
+    public native void setGraphicSelection(int type, int x, int y);
+
+    /**
+     * Reset current (any kind of) selection.
+     */
+    public native void resetSelection();
+
+    /**
      * Callback to retrieve messages from LOK
      */
     public interface MessageCallback {
diff --git a/desktop/source/lib/lokandroid.cxx b/desktop/source/lib/lokandroid.cxx
index 528ffe1..b4d0e98 100644
--- a/desktop/source/lib/lokandroid.cxx
+++ b/desktop/source/lib/lokandroid.cxx
@@ -291,6 +291,20 @@ extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Document_setText
     pDocument->pClass->setTextSelection(pDocument, type, x, y);
 }
 
+extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Document_setGraphicSelection
+    (JNIEnv* pEnv, jobject aObject, jint type, jint x, jint y)
+{
+    LibreOfficeKitDocument* pDocument = getHandle<LibreOfficeKitDocument>(pEnv, aObject);
+    pDocument->pClass->setGraphicSelection(pDocument, type, x, y);
+}
+
+extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Document_resetSelection
+    (JNIEnv* pEnv, jobject aObject)
+{
+    LibreOfficeKitDocument* pDocument = getHandle<LibreOfficeKitDocument>(pEnv, aObject);
+    pDocument->pClass->resetSelection(pDocument);
+}
+
 /* DirectBufferAllocator */
 
 extern "C" SAL_JNI_EXPORT jobject JNICALL Java_org_libreoffice_kit_DirectBufferAllocator_allocateDirectBufferNative
commit bcc3163a4a028526cd1dad86cc7a452d952d704f
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Mar 11 17:23:25 2015 +0900

    android: add bold selection to toolbar (experimental)
    
    Change-Id: Ie9fa613659db9dcc174851d7c02587bef6b67cef

diff --git a/android/experimental/LOAndroid3/res/menu/main.xml b/android/experimental/LOAndroid3/res/menu/main.xml
index cdf83bb..52f4ebc 100644
--- a/android/experimental/LOAndroid3/res/menu/main.xml
+++ b/android/experimental/LOAndroid3/res/menu/main.xml
@@ -3,6 +3,13 @@
     xmlns:tools="http://schemas.android.com/tools"
     tools:context="org.libreoffice.MainActivity">
 
+
+    <item android:id="@+id/action_bold"
+          android:title="@string/action_bold"
+          android:icon="@drawable/ic_format_bold_grey600_24dp"
+          android:orderInCategory="100"
+          app:showAsAction="always"/>
+
     <item android:id="@+id/action_about"
         android:title="@string/action_about"
         android:orderInCategory="100" />
diff --git a/android/experimental/LOAndroid3/res/values/strings.xml b/android/experimental/LOAndroid3/res/values/strings.xml
index 5e5e80e..e2c6ffc 100644
--- a/android/experimental/LOAndroid3/res/values/strings.xml
+++ b/android/experimental/LOAndroid3/res/values/strings.xml
@@ -34,5 +34,6 @@
     <!-- Document provider names -->
     <string name="local_documents">Local documents</string>
     <string name="local_file_system">Local file system</string>
+    <string name="action_bold">Bold</string>
 
 </resources>
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index 4695b1b..c0e4810 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -18,6 +18,7 @@ import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView;
 import android.widget.ListView;
 import android.widget.RelativeLayout;
+import android.widget.Toast;
 
 import org.mozilla.gecko.TextSelection;
 import org.mozilla.gecko.ZoomConstraints;
@@ -75,6 +76,9 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
     public boolean onOptionsItemSelected(MenuItem item) {
         int id = item.getItemId();
         switch (id) {
+            case R.id.action_bold:
+                Toast.makeText(this,"set text to bold", Toast.LENGTH_LONG).show();
+                return true;
             case R.id.action_about:
                 mAbout.showAbout();
                 return true;
commit 598ba92da81c03f2063d370dc096f05184ab183f
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Mar 11 17:04:03 2015 +0900

    android: add toolbar controller
    
    Change-Id: I9ecaf0f0e7e39e2a28e1545bc0310360d5cebfe5

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
index 4c3a2ba..1ac35d9 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/InvalidationHandler.java
@@ -250,7 +250,7 @@ public class InvalidationHandler implements Document.MessageCallback {
 
     private synchronized void changeState(OverlayState previous, OverlayState next) {
         mState = next;
-
+        handleGeneralChangeState(previous, next);
         switch (next) {
             case CURSOR:
                 handleCursorState(previous);
@@ -270,6 +270,14 @@ public class InvalidationHandler implements Document.MessageCallback {
         }
     }
 
+    private void handleGeneralChangeState(OverlayState previous, OverlayState next) {
+        if (previous == OverlayState.NONE) {
+            LOKitShell.getToolbarController().switchToEditMode();
+        } else if (next == OverlayState.NONE) {
+            LOKitShell.getToolbarController().switchToViewMode();
+        }
+    }
+
     private void handleNoneState(OverlayState previous) {
         if (previous == OverlayState.NONE) {
             return;
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
index 6c2e921..1d3e018 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitShell.java
@@ -47,6 +47,10 @@ public class LOKitShell {
         });
     }
 
+    public static ToolbarController getToolbarController() {
+        return LibreOfficeMainActivity.mAppContext.getToolbarController();
+    }
+
     public static int getMemoryClass(Context context) {
         ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         return activityManager.getMemoryClass() * 1024 * 1024;
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index a5fe244..ea7cc31 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -214,16 +214,7 @@ public class LOKitThread extends Thread {
                 onSwipeRight();
                 break;
             case LOEvent.NAVIGATION_CLICK:
-                if (mInvalidationHandler.getCurrentState() == InvalidationHandler.OverlayState.NONE) {
-                    LOKitShell.getMainHandler().post(new Runnable() {
-                        @Override
-                        public void run() {
-                            LibreOfficeMainActivity.mAppContext.onBackPressed();
-                        }
-                    });
-                } else {
-                    mInvalidationHandler.changeStateTo(InvalidationHandler.OverlayState.NONE);
-                }
+                mInvalidationHandler.changeStateTo(InvalidationHandler.OverlayState.NONE);
                 break;
         }
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
index bf1a1b7..4695b1b 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -54,6 +54,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
     private TextCursorLayer mTextCursorLayer;
     private File mTempFile = null;
     private LOAbout mAbout;
+    private ToolbarController mToolbarController;
 
     public LibreOfficeMainActivity() {
         mAbout = new LOAbout(this, false);
@@ -120,9 +121,7 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
 
         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
-        getSupportActionBar().setHomeAsUpIndicator(R.drawable.lo_icon);
-
-        //getSupportActionBar().setHomeAsUpIndicator();
+        mToolbarController = new ToolbarController(getSupportActionBar(), toolbar);
 
         toolbar.setNavigationOnClickListener(new View.OnClickListener() {
             @Override
@@ -324,6 +323,10 @@ public class LibreOfficeMainActivity extends ActionBarActivity {
         return mTextCursorLayer;
     }
 
+    public ToolbarController getToolbarController() {
+        return mToolbarController;
+    }
+
     private class DocumentPartClickListener implements android.widget.AdapterView.OnItemClickListener {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/ToolbarController.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/ToolbarController.java
new file mode 100644
index 0000000..7c4d7b8
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/ToolbarController.java
@@ -0,0 +1,38 @@
+package org.libreoffice;
+
+import android.support.v7.app.ActionBar;
+import android.support.v7.widget.Toolbar;
+
+public class ToolbarController {
+    private final Toolbar mToolbar;
+    private final ActionBar mActionBar;
+
+    public ToolbarController(ActionBar actionBar, Toolbar toolbar) {
+        mToolbar = toolbar;
+        mActionBar = actionBar;
+        switchToViewMode();
+    }
+
+    void switchToEditMode() {
+        LOKitShell.getMainHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                mActionBar.setDisplayHomeAsUpEnabled(false);
+                mToolbar.setNavigationIcon(R.drawable.ic_check_grey600_24dp);
+                mToolbar.setTitle(null);
+
+            }
+        });
+    }
+
+    void switchToViewMode() {
+        LOKitShell.getMainHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                mToolbar.setNavigationIcon(R.drawable.ic_menu_grey600_24dp);
+                mToolbar.setTitle("LibreOffice");
+                mActionBar.setDisplayHomeAsUpEnabled(true);
+            }
+        });
+    }
+}
commit 2c0498dcce50f0b524d7b895945e596775c2da14
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Mar 11 16:54:30 2015 +0900

    android: add some material design icons
    
    Change-Id: Ieb6acdb75e0ae0367dd39b2773e69d6f8415f0fc

diff --git a/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_check_grey600_24dp.png b/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_check_grey600_24dp.png
new file mode 100644
index 0000000..c489968
Binary files /dev/null and b/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_check_grey600_24dp.png differ
diff --git a/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_format_bold_grey600_24dp.png b/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_format_bold_grey600_24dp.png
new file mode 100644
index 0000000..2d7688a
Binary files /dev/null and b/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_format_bold_grey600_24dp.png differ
diff --git a/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_menu_grey600_24dp.png b/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_menu_grey600_24dp.png
new file mode 100644
index 0000000..1eab3a7
Binary files /dev/null and b/android/experimental/LOAndroid3/res/drawable-xxxhdpi/ic_menu_grey600_24dp.png differ
commit 1b3343410ae97c19ce62f7700ee48df9532a0bda
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Mar 11 09:21:13 2015 +0100

    lokdocview: cppcheck: variableScope
    
    Change-Id: Ib91bfea95d957362d807a3de53b12e2fc9389fbb

diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index ece113d..8349256 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -67,12 +67,10 @@ void lcl_getDragPoint(GdkRectangle* pHandle, GdkEventButton* pEvent, GdkPoint* p
     pPoint->y = aCursor.y + (pEvent->y - aHandle.y);
 }
 
-gboolean lcl_signalMotion(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocView* pDocView)
+gboolean lcl_signalMotion(GtkWidget* /*pEventBox*/, GdkEventButton* pEvent, LOKDocView* pDocView)
 {
     GdkPoint aPoint;
-    int i;
 
-    (void)pEventBox;
     if (pDocView->m_bInDragMiddleHandle)
     {
         g_info("lcl_signalMotion: dragging the middle handle");
@@ -100,7 +98,7 @@ gboolean lcl_signalMotion(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocVi
                 pixelToTwip(aPoint.x) / pDocView->fZoom, pixelToTwip(aPoint.y) / pDocView->fZoom);
         return FALSE;
     }
-    for (i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
+    for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
     {
         if (pDocView->m_bInDragGraphicHandles[i])
         {
@@ -117,15 +115,12 @@ gboolean lcl_signalMotion(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocVi
 }
 
 /// Receives a button press event.
-gboolean lcl_signalButton(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocView* pDocView)
+gboolean lcl_signalButton(GtkWidget* /*pEventBox*/, GdkEventButton* pEvent, LOKDocView* pDocView)
 {
     g_info("lcl_signalButton: %d, %d (in twips: %d, %d)", (int)pEvent->x, (int)pEvent->y, (int)pixelToTwip(pEvent->x), (int)pixelToTwip(pEvent->y));
-    (void) pEventBox;
 
     if (pEvent->type == GDK_BUTTON_RELEASE)
     {
-        int i;
-
         if (pDocView->m_bInDragStartHandle)
         {
             g_info("lcl_signalButton: end of drag start handle");
@@ -145,7 +140,7 @@ gboolean lcl_signalButton(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocVi
             return FALSE;
         }
 
-        for (i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
+        for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
         {
             if (pDocView->m_bInDragGraphicHandles[i])
             {
@@ -179,7 +174,6 @@ gboolean lcl_signalButton(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocVi
         aClick.height = 1;
         if (pEvent->type == GDK_BUTTON_PRESS)
         {
-            int i;
             GdkRectangle aClickInTwips;
 
             if (gdk_rectangle_intersect(&aClick, &pDocView->m_aHandleStartRect, NULL))
@@ -201,7 +195,7 @@ gboolean lcl_signalButton(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocVi
                 return FALSE;
             }
 
-            for (i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
+            for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
             {
                 if (gdk_rectangle_intersect(&aClick, &pDocView->m_aGraphicHandleRects[i], NULL))
                 {
@@ -455,7 +449,6 @@ static void lcl_renderGraphicHandle(cairo_t* pCairo, GdkRectangle* pSelection, c
 {
     int nHandleWidth, nHandleHeight;
     GdkRectangle aSelection;
-    int i;
 
     nHandleWidth = cairo_image_surface_get_width(pHandle);
     nHandleHeight = cairo_image_surface_get_height(pHandle);
@@ -465,7 +458,7 @@ static void lcl_renderGraphicHandle(cairo_t* pCairo, GdkRectangle* pSelection, c
     aSelection.width = twipToPixel(pSelection->width) * fZoom;
     aSelection.height = twipToPixel(pSelection->height) * fZoom;
 
-    for (i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
+    for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
     {
         int x = aSelection.x, y = aSelection.y;
         cairo_save(pCairo);
@@ -516,13 +509,12 @@ static void lcl_renderGraphicHandle(cairo_t* pCairo, GdkRectangle* pSelection, c
     }
 }
 
-static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* pEvent, gpointer pData)
+static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* /*pEvent*/, gpointer pData)
 {
 #if GTK_CHECK_VERSION(2,14,0) // we need gtk_widget_get_window()
     LOKDocView* pDocView = LOK_DOCVIEW(pData);
     cairo_t* pCairo;
 
-    (void)pEvent;
     pCairo = gdk_cairo_create(gtk_widget_get_window(pWidget));
 
     if (pDocView->m_bEdit && pDocView->m_bCursorVisible && pDocView->m_bCursorOverlayVisible && !lcl_isEmptyRectangle(&pDocView->m_aVisibleCursor))
@@ -553,9 +545,7 @@ static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* pEvent, gpoint
 
     if (pDocView->m_pTextSelectionRectangles)
     {
-        GList* i;
-
-        for (i = pDocView->m_pTextSelectionRectangles; i != NULL; i = i->next)
+        for (GList* i = pDocView->m_pTextSelectionRectangles; i != NULL; i = i->next)
         {
             GdkRectangle* pRectangle = static_cast<GdkRectangle*>(i->data);
             // Blue with 75% transparency.
@@ -603,19 +593,16 @@ static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* pEvent, gpoint
 
 void renderDocument(LOKDocView* pDocView, GdkRectangle* pPartial)
 {
-    long nDocumentWidthTwips, nDocumentHeightTwips, nDocumentWidthPixels, nDocumentHeightPixels;
     const int nTileSizePixels = 256;
-    // Current row / column.
-    guint nRow, nColumn;
-    // Total number of rows / columns in this document.
-    guint nRows, nColumns;
 
     // Get document size and find out how many rows / columns we need.
+    long nDocumentWidthTwips, nDocumentHeightTwips;
     pDocView->pDocument->pClass->getDocumentSize(pDocView->pDocument, &nDocumentWidthTwips, &nDocumentHeightTwips);
-    nDocumentWidthPixels = twipToPixel(nDocumentWidthTwips) * pDocView->fZoom;
-    nDocumentHeightPixels = twipToPixel(nDocumentHeightTwips) * pDocView->fZoom;
-    nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
-    nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
+    long nDocumentWidthPixels = twipToPixel(nDocumentWidthTwips) * pDocView->fZoom;
+    long nDocumentHeightPixels = twipToPixel(nDocumentHeightTwips) * pDocView->fZoom;
+    // Total number of rows / columns in this document.
+    guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
+    guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
 
     // Set up our table and the tile pointers.
     if (!pDocView->pTable)
@@ -647,9 +634,9 @@ void renderDocument(LOKDocView* pDocView, GdkRectangle* pPartial)
     }
 
     // Render the tiles.
-    for (nRow = 0; nRow < nRows; ++nRow)
+    for (guint nRow = 0; nRow < nRows; ++nRow)
     {
-        for (nColumn = 0; nColumn < nColumns; ++nColumn)
+        for (guint nColumn = 0; nColumn < nColumns; ++nColumn)
         {
             GdkRectangle aTileRectangleTwips, aTileRectanglePixels;
             gboolean bPaint = TRUE;
@@ -676,13 +663,11 @@ void renderDocument(LOKDocView* pDocView, GdkRectangle* pPartial)
             {
                 // Index of the current tile.
                 guint nTile = nRow * nColumns + nColumn;
-                GdkPixbuf* pPixBuf;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list