[Libreoffice-commits] core.git: 24 commits - android/Bootstrap android/experimental desktop/source include/LibreOfficeKit libreofficekit/qa libreofficekit/source sal/android vcl/inc

Miklos Vajna vmiklos at collabora.co.uk
Mon Jan 12 02:07:33 PST 2015


 android/Bootstrap/Makefile.shared                                                     |    3 
 android/Bootstrap/src/org/libreoffice/kit/Document.java                               |   27 +++
 android/Bootstrap/src/org/libreoffice/kit/Office.java                                 |    2 
 android/experimental/LOAndroid3/AndroidManifest.xml.in                                |    2 
 android/experimental/LOAndroid3/res/layout/about.xml                                  |    9 +
 android/experimental/LOAndroid3/res/values/strings.xml                                |    1 
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOAbout.java                 |   23 ++
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java                 |   16 +
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java          |    9 -
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java             |   33 +++
 android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java       |   61 +++++--
 android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java        |    8 
 android/experimental/LOAndroid3/src/java/org/libreoffice/TileIdentifier.java          |    5 
 android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java            |    9 +
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java |   12 +
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java  |   23 +-
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java     |    3 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java         |    8 
 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java         |    5 
 desktop/source/lib/init.cxx                                                           |   18 ++
 desktop/source/lib/lokandroid.cxx                                                     |   85 +++++++++-
 include/LibreOfficeKit/LibreOfficeKit.h                                               |   32 ++-
 include/LibreOfficeKit/LibreOfficeKit.hxx                                             |   11 +
 include/LibreOfficeKit/LibreOfficeKitGtk.h                                            |    2 
 libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx                                   |   16 +
 libreofficekit/source/gtk/lokdocview.c                                                |   17 +-
 sal/android/lo-bootstrap.c                                                            |    2 
 vcl/inc/headless/svpframe.hxx                                                         |    4 
 28 files changed, 389 insertions(+), 57 deletions(-)

New commits:
commit 4f1eef278c41997315860158d481d4fc37bd328b
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Jan 12 09:35:26 2015 +0100

    android: show version / buildid in about dialog
    
    Note that getPackageName() also throws NameNotFoundException, so in the
    unlikely situations in case:
    
    - package info (class containing the package version) is not found or
    - the package version is not in an "a/b" form
    
    We still just don't show anything.
    
    Also, mark the new TextView as android:textIsSelectable, so it's
    possible to copy&paste the version for bugreport purposes.
    
    Change-Id: I63b53cca4126da17bfbda0293d7c98e8524ef41a

diff --git a/android/Bootstrap/Makefile.shared b/android/Bootstrap/Makefile.shared
index 82513df..ee50d1f 100644
--- a/android/Bootstrap/Makefile.shared
+++ b/android/Bootstrap/Makefile.shared
@@ -180,8 +180,9 @@ copy-stuff:
 	echo '[Version]' > assets/program/versionrc
 	echo 'AllLanguages=en-US' >> assets/program/versionrc
 	echo 'BuildVersion=' >> assets/program/versionrc
-	echo 'buildid=dead-beef' >> assets/program/versionrc
+	echo 'buildid=$(shell cd $(SRCDIR) && git log -1 --format=%H)' >> assets/program/versionrc
 	echo 'ReferenceOOoMajorMinor=4.1' >> assets/program/versionrc
+	sed -i 's|android:versionName=".*"|android:versionName="$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)$(LIBO_VERSION_SUFFIX)$(LIBO_VERSION_SUFFIX_SUFFIX)/$(shell cd $(SRCDIR) && git log -1 --format=%H)"|' AndroidManifest.xml
 #
 # .res files
 	mkdir -p assets/program/resource
diff --git a/android/experimental/LOAndroid3/AndroidManifest.xml.in b/android/experimental/LOAndroid3/AndroidManifest.xml.in
index 6b339e7..360687e 100644
--- a/android/experimental/LOAndroid3/AndroidManifest.xml.in
+++ b/android/experimental/LOAndroid3/AndroidManifest.xml.in
@@ -3,7 +3,7 @@
     package="org.libreoffice"
     @ANDROID_INSTALL_LOCATION@
     android:versionCode="1"
-    android:versionName="1.0">
+    android:versionName="@ANDROID_VERSION@">
 
     <!-- App requires OpenGL ES 2.0 -->
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
diff --git a/android/experimental/LOAndroid3/res/layout/about.xml b/android/experimental/LOAndroid3/res/layout/about.xml
index 06c5bfe..c15f0cc 100644
--- a/android/experimental/LOAndroid3/res/layout/about.xml
+++ b/android/experimental/LOAndroid3/res/layout/about.xml
@@ -7,6 +7,15 @@
               android:padding="20dip">
 
     <TextView
+        android:id="@+id/about_version"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textIsSelectable="true"
+        android:text="@string/app_version"
+        android:textColor="@android:color/secondary_text_light"
+        android:textSize="18sp"/>
+
+    <TextView
         android:id="@+id/about_description"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/android/experimental/LOAndroid3/res/values/strings.xml b/android/experimental/LOAndroid3/res/values/strings.xml
index 473616a..2d03388 100644
--- a/android/experimental/LOAndroid3/res/values/strings.xml
+++ b/android/experimental/LOAndroid3/res/values/strings.xml
@@ -4,6 +4,7 @@
     <string name="app_name">LibreOffice Viewer</string>
 
     <string name="app_about_name"><b>LibreOffice Viewer \'Beta\'</b></string>
+    <string name="app_version">Version: $VERSION\nBuild ID: $BUILDID</string>
     <string name="app_description">LibreOffice Viewer is a document viewer based on LibreOffice.</string>
     <string name="app_credits">http://www.libreoffice.org</string>
 
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOAbout.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOAbout.java
index 2b3bf31..1aca1c6 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOAbout.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOAbout.java
@@ -19,6 +19,7 @@ import android.widget.RelativeLayout;
 import android.widget.TextView;
 import android.content.Intent;
 import android.net.Uri;
+import android.content.pm.PackageManager.NameNotFoundException;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -58,6 +59,28 @@ public abstract class LOAbout extends Activity {
         int defaultColor = textView.getTextColors().getDefaultColor();
         textView.setTextColor(defaultColor);
 
+        // Take care of placeholders in the version text view.
+        textView = (TextView)messageView.findViewById(R.id.about_version);
+        try
+        {
+            String versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
+            String[] tokens = versionName.split("/");
+            if (tokens.length == 2)
+            {
+                String version = textView.getText().toString();
+                version = version.replace("$VERSION", tokens[0]);
+                version = version.replace("$BUILDID", tokens[1]);
+                textView.setText(version);
+            }
+            else
+                throw new NameNotFoundException();
+        }
+        catch (NameNotFoundException e)
+        {
+            textView.setText("");
+        }
+
+
         AlertDialog.Builder builder = new AlertDialog.Builder(this);
         builder.setIcon(R.drawable.lo_icon);
         builder.setTitle(R.string.app_name);
commit 723b6a07e4c4dfb8fdafc186041557514b014014
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Mon Jan 12 16:35:10 2015 +0900

    jni: add postKeyEvent to Office and redirect the call to LOK
    
    Change-Id: I922ce1f735df236d2bdad33820ed98f18fc85963

diff --git a/android/Bootstrap/src/org/libreoffice/kit/Office.java b/android/Bootstrap/src/org/libreoffice/kit/Office.java
index e7d26c5..8759e85 100644
--- a/android/Bootstrap/src/org/libreoffice/kit/Office.java
+++ b/android/Bootstrap/src/org/libreoffice/kit/Office.java
@@ -32,6 +32,8 @@ public class Office {
         return document;
     }
 
+    public native void postKeyEvent(int type, int code);
+
     public native void destroy();
     public native void destroyAndExit();
 }
diff --git a/desktop/source/lib/lokandroid.cxx b/desktop/source/lib/lokandroid.cxx
index 06da8a9..773cba5 100644
--- a/desktop/source/lib/lokandroid.cxx
+++ b/desktop/source/lib/lokandroid.cxx
@@ -51,14 +51,16 @@ const char* copyJavaString(JNIEnv* pEnv, jstring aJavaString)
 
 } // anonymous namespace
 
-extern "C" SAL_JNI_EXPORT jstring JNICALL Java_org_libreoffice_kit_Office_getError(JNIEnv* pEnv, jobject aObject)
+extern "C" SAL_JNI_EXPORT jstring JNICALL Java_org_libreoffice_kit_Office_getError
+    (JNIEnv* pEnv, jobject aObject)
 {
     LibreOfficeKit* pLibreOfficeKit = getHandle<LibreOfficeKit>(pEnv, aObject);
     char* pError = pLibreOfficeKit->pClass->getError(pLibreOfficeKit);
     return pEnv->NewStringUTF(pError);
 }
 
-extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Office_destroy(JNIEnv* pEnv, jobject aObject)
+extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Office_destroy
+    (JNIEnv* pEnv, jobject aObject)
 {
     LibreOfficeKit* pLibreOfficeKit = getHandle<LibreOfficeKit>(pEnv, aObject);
     pLibreOfficeKit->pClass->destroy(pLibreOfficeKit);
@@ -73,6 +75,13 @@ extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Office_destroyAn
     _exit(0);
 }
 
+extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Office_postKeyEvent
+    (JNIEnv* pEnv, jobject aObject, jint nType, jint nCode)
+{
+    LibreOfficeKit* pLibreOfficeKit = getHandle<LibreOfficeKit>(pEnv, aObject);
+    pLibreOfficeKit->pClass->postKeyEvent(pLibreOfficeKit, nType, nCode);
+}
+
 namespace
 {
 
@@ -122,7 +131,8 @@ void messageCallback(int nType, const char* pPayload, void* pData)
 
 } // anonymous namespace
 
-extern "C" SAL_JNI_EXPORT jobject JNICALL Java_org_libreoffice_kit_Office_documentLoadNative(JNIEnv* pEnv, jobject aObject, jstring documentPath)
+extern "C" SAL_JNI_EXPORT jobject JNICALL Java_org_libreoffice_kit_Office_documentLoadNative
+    (JNIEnv* pEnv, jobject aObject, jstring documentPath)
 {
     const char* aCloneDocumentPath = copyJavaString(pEnv, documentPath);
     LibreOfficeKit* pLibreOfficeKit = getHandle<LibreOfficeKit>(pEnv, aObject);
commit 9f77740d8b8112de1b157abd892307e057b4f265
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Mon Jan 12 14:51:27 2015 +0900

    android: force screen to render - add access to LayerClient
    
    Change-Id: Ia65eebd153251985fe736e8f278d46b22a06ec83

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index a37caa7..4063a84 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -34,20 +34,19 @@ public class LOKitThread extends Thread implements TileProvider.TileInvalidation
             composedTileLayer.addTile(tile);
             mLayerClient.endDrawing(mViewportMetrics);
             if (forceRedraw) {
-                Log.i(LOGTAG, "Redrawing tile " + tileId);
-                mLayerClient.forceRedraw();
+                mLayerClient.forceRender();
             }
         }
     }
 
     private void tileRerender(ComposedTileLayer composedTileLayer, SubTile tile) {
-        if (composedTileLayer.isStillValid(tile.id)) {
+        if (composedTileLayer.isStillValid(tile.id) && !tile.markedForRemoval) {
+            Log.i(LOGTAG, "Redrawing tile " + tile.id);
             mLayerClient.beginDrawing();
             mTileProvider.rerenderTile(tile.getImage(), tile.id.x, tile.id.y, tile.id.size, tile.id.zoom);
             tile.invalidate();
-            Log.i(LOGTAG, "Redrawing tile " + tile.id);
-            mLayerClient.forceRedraw();
             mLayerClient.endDrawing(mViewportMetrics);
+            mLayerClient.forceRender();
         }
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index c1849d1..1bb15bc 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -397,6 +397,14 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener {
         }
     }
 
+    public void forceRender() {
+        post(new Runnable() {
+            public void run() {
+                mView.requestRender();
+            }
+        });
+    }
+
     /** Implementation of PanZoomTarget */
     public boolean post(Runnable action) {
         return mView.post(action);
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
index d359502..3d0ff1f 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
@@ -73,7 +73,6 @@ public abstract class TileLayer extends Layer {
      * Invalidates the entire buffer so that it will be uploaded again. Only valid inside a
      * transaction.
      */
-
     public void invalidate() {
         if (!inTransaction())
             throw new RuntimeException("invalidate() is only valid inside a transaction");
commit 0ecf41b4b1ea995beab8ee79d608360f69a40040
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Mon Jan 12 14:49:39 2015 +0900

    android: remove checkerboard color property - fix set to white
    
    Change-Id: I7a11b0eea71e96f8bd2b307539f1964acb240216

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index 676e73c..c1849d1 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -96,7 +96,6 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener {
         DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
         mViewportMetrics = new ImmutableViewportMetrics(displayMetrics);
         mZoomConstraints = new ZoomConstraints(false);
-        mCheckerboardColor = Color.WHITE;
 
         mPanZoomController = PanZoomController.Factory.create(this);
     }
@@ -247,15 +246,6 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener {
         }
     }
 
-    int getCheckerboardColor() {
-        return mCheckerboardColor;
-    }
-
-    public void setCheckerboardColor(int newColor) {
-        mCheckerboardColor = newColor;
-        mView.requestRender();
-    }
-
     public void setZoomConstraints(ZoomConstraints constraints) {
         mZoomConstraints = constraints;
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
index 7b4ead3..6fe97b8 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
@@ -8,6 +8,7 @@ package org.mozilla.gecko.gfx;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.graphics.Bitmap;
+import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -571,7 +572,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
             GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
 
             /* Update background color. */
-            mBackgroundColor = mView.getLayerClient().getCheckerboardColor();
+            mBackgroundColor = Color.WHITE;
 
             /* Clear to the page background colour. The bits set here need to
              * match up with those used in gfx/layers/opengl/LayerManagerOGL.cpp.
commit 9563293912d2d25989c4f869e58000c78487455a
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Jan 9 18:12:52 2015 +0100

    gtktiledviewer: invoke paintTile() on the main thread from the callback
    
    Change-Id: Id910c1905d23f16cae5b6b551c74193d46cff256

diff --git a/libreofficekit/source/gtk/lokdocview.c b/libreofficekit/source/gtk/lokdocview.c
index 903f7e3..65fdbfd 100644
--- a/libreofficekit/source/gtk/lokdocview.c
+++ b/libreofficekit/source/gtk/lokdocview.c
@@ -149,7 +149,16 @@ void renderDocument( LOKDocView* pDocView )
     gtk_image_set_from_pixbuf( GTK_IMAGE( pDocView->pCanvas ), pDocView->pPixBuf );
 }
 
-static void lok_docview_callback(int nType, const char* pPayload, void* pData)
+/// Invoked on the main thread if lok_docview_callback_worker() requests so.
+static gboolean lok_docview_callback(gpointer pData)
+{
+    LOKDocView* pDocView = pData;
+    renderDocument(pDocView);
+    return G_SOURCE_REMOVE;
+}
+
+/// Our LOK callback, runs on the LO thread.
+static void lok_docview_callback_worker(int nType, const char* pPayload, void* pData)
 {
     LOKDocView* pDocView = pData;
 
@@ -158,7 +167,7 @@ static void lok_docview_callback(int nType, const char* pPayload, void* pData)
     case LOK_CALLBACK_INVALIDATE_TILES:
         // TODO for now just always render the document.
         (void)pPayload;
-        renderDocument( pDocView );
+        gdk_threads_add_idle(lok_docview_callback, pDocView);
         break;
     default:
         break;
@@ -185,7 +194,7 @@ SAL_DLLPUBLIC_EXPORT gboolean lok_docview_open_document( LOKDocView* pDocView, c
     else
     {
         renderDocument( pDocView );
-        pDocView->pDocument->pClass->registerCallback(pDocView->pDocument, &lok_docview_callback, pDocView);
+        pDocView->pDocument->pClass->registerCallback(pDocView->pDocument, &lok_docview_callback_worker, pDocView);
     }
 
     return TRUE;
commit e9c6949435bf4eb961eb2a1cf868b11df1373bb1
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 20:24:38 2015 +0900

    android: reuse rerenderTile in createTile
    
    Change-Id: Ibafdcf5dd54804b4c50dd51d9a5a89dc7088052d

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index d8e11bc..fe389ef 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -189,25 +189,8 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback
     @Override
     public CairoImage createTile(float x, float y, IntSize tileSize, float zoom) {
         ByteBuffer buffer = ByteBuffer.allocateDirect(tileSize.width * tileSize.height * 4);
-
-        if (mDocument != null) {
-            float twipX = pixelToTwip(x, mDPI) / zoom;
-            float twipY = pixelToTwip(y, mDPI) / zoom;
-            float twipWidth = mTileWidth / zoom;
-            float twipHeight = mTileHeight / zoom;
-            long start = System.currentTimeMillis() - objectCreationTime;
-
-            //Log.i(LOGTAG, "paintTile >> @" + start + " (" + tileSize.width + " " + tileSize.height + " " + (int) twipX + " " + (int) twipY + " " + (int) twipWidth + " " + (int) twipHeight + ")");
-            mDocument.paintTile(buffer, tileSize.width, tileSize.height, (int) twipX, (int) twipY, (int) twipWidth, (int) twipHeight);
-
-            long stop = System.currentTimeMillis() - objectCreationTime;
-            //Log.i(LOGTAG, "paintTile << @" + stop + " elapsed: " + (stop - start));
-        } else {
-            Log.e(LOGTAG, "Document is null!!");
-        }
-
         CairoImage image = new BufferedCairoImage(buffer, tileSize.width, tileSize.height, CairoImage.FORMAT_ARGB32);
-
+        rerenderTile(image, x, y, tileSize, zoom);
         return image;
     }
 
@@ -218,8 +201,13 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback
             float twipY = pixelToTwip(y, mDPI) / zoom;
             float twipWidth = mTileWidth / zoom;
             float twipHeight = mTileHeight / zoom;
+            long start = System.currentTimeMillis() - objectCreationTime;
 
+            //Log.i(LOGTAG, "paintTile >> @" + start + " (" + tileSize.width + " " + tileSize.height + " " + (int) twipX + " " + (int) twipY + " " + (int) twipWidth + " " + (int) twipHeight + ")");
             mDocument.paintTile(image.getBuffer(), tileSize.width, tileSize.height, (int) twipX, (int) twipY, (int) twipWidth, (int) twipHeight);
+
+            long stop = System.currentTimeMillis() - objectCreationTime;
+            //Log.i(LOGTAG, "paintTile << @" + stop + " elapsed: " + (stop - start));
         } else {
             if (mDocument == null) {
                 Log.e(LOGTAG, "Document is null!!");
commit 8da64996c98daae4b49ed0b73b6f690f9c0a0e3c
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 19:55:30 2015 +0900

    android: bypass Bitmap creation and copying when creating tiles
    
    Copying tile buffer just because we can is not really a good idea
    when just using the buffer in CairoImage works perfectly well. This
    should speed things up a bit but probably won't be noticable.
    
    Change-Id: I8d191d3e3870b20b15db56841ed72da22546aefc

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index a70b0bc..d8e11bc 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -189,7 +189,6 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback
     @Override
     public CairoImage createTile(float x, float y, IntSize tileSize, float zoom) {
         ByteBuffer buffer = ByteBuffer.allocateDirect(tileSize.width * tileSize.height * 4);
-        Bitmap bitmap = Bitmap.createBitmap(tileSize.width, tileSize.height, Bitmap.Config.ARGB_8888);
 
         if (mDocument != null) {
             float twipX = pixelToTwip(x, mDPI) / zoom;
@@ -207,9 +206,7 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback
             Log.e(LOGTAG, "Document is null!!");
         }
 
-        bitmap.copyPixelsFromBuffer(buffer);
-
-        CairoImage image = new BufferedCairoImage(bitmap);
+        CairoImage image = new BufferedCairoImage(buffer, tileSize.width, tileSize.height, CairoImage.FORMAT_ARGB32);
 
         return image;
     }
commit 2cd20fa87b69dfb7d5326ace04bac48414158733
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 19:45:15 2015 +0900

    android: support to rerender tile buffer directly
    
    Add new event TILE_RERENDER to the LOEvent and handle rerender
    so that the tile's image buffer is rerendered and the tile
    invalidated (instead of creating a new tile and deleting the old
    one).
    
    Change-Id: Id0fec307cb82c44a8584425dc7f877f39955844b

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
index 77ad269..5b13da4 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
@@ -2,9 +2,9 @@ package org.libreoffice;
 
 import org.mozilla.gecko.gfx.ComposedTileLayer;
 import org.mozilla.gecko.gfx.IntSize;
+import org.mozilla.gecko.gfx.SubTile;
 
 public class LOEvent implements Comparable<LOEvent> {
-
     public static final int SIZE_CHANGED = 1;
     public static final int TILE_SIZE = 2;
     public static final int CHANGE_PART = 3;
@@ -13,6 +13,7 @@ public class LOEvent implements Comparable<LOEvent> {
     public static final int REDRAW = 6;
     public static final int TILE_REQUEST = 7;
     public static final int THUMBNAIL = 8;
+    public static final int TILE_RERENDER = 9;
 
     public final int mType;
     public int mPriority = 0;
@@ -24,6 +25,7 @@ public class LOEvent implements Comparable<LOEvent> {
     public TileIdentifier mTileId;
     public ComposedTileLayer mComposedTileLayer;
     public boolean mForceRedraw;
+    public SubTile mTile;
 
     public LOEvent(int type) {
         mType = type;
@@ -64,6 +66,13 @@ public class LOEvent implements Comparable<LOEvent> {
         mTask = task;
     }
 
+    public LOEvent(int type, ComposedTileLayer composedTileLayer, SubTile tile) {
+        mType = type;
+        mTypeString = "Tile Rerender";
+        mComposedTileLayer = composedTileLayer;
+        mTile = tile;
+    }
+
     public String getTypeString() {
         if (mTypeString == null) {
             return "Event type: " + mType;
@@ -75,4 +84,5 @@ public class LOEvent implements Comparable<LOEvent> {
     public int compareTo(LOEvent another) {
         return mPriority - another.mPriority;
     }
+
 }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java
index 169c46e..b866850 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java
@@ -2,6 +2,7 @@ package org.libreoffice;
 
 import org.mozilla.gecko.gfx.ComposedTileLayer;
 import org.mozilla.gecko.gfx.IntSize;
+import org.mozilla.gecko.gfx.SubTile;
 
 
 public class LOEventFactory {
@@ -29,11 +30,15 @@ public class LOEventFactory {
         return new LOEvent(LOEvent.REDRAW);
     }
 
-    public static LOEvent tileRequest(ComposedTileLayer composedTileLayer, TileIdentifier tileRequest, boolean forceRedraw) {
-        return new LOEvent(LOEvent.TILE_REQUEST, composedTileLayer, tileRequest, forceRedraw);
+    public static LOEvent tileRequest(ComposedTileLayer composedTileLayer, TileIdentifier tileID, boolean forceRedraw) {
+        return new LOEvent(LOEvent.TILE_REQUEST, composedTileLayer, tileID, forceRedraw);
     }
 
     public static LOEvent thumbnail(ThumbnailCreator.ThumbnailCreationTask task) {
         return new LOEvent(LOEvent.THUMBNAIL, task);
     }
+
+    public static LOEvent tileRerender(ComposedTileLayer composedTileLayer, SubTile tile) {
+        return new LOEvent(LOEvent.TILE_RERENDER, composedTileLayer, tile);
+    }
 }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index 98b4d03..a37caa7 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -40,6 +40,18 @@ public class LOKitThread extends Thread implements TileProvider.TileInvalidation
         }
     }
 
+    private void tileRerender(ComposedTileLayer composedTileLayer, SubTile tile) {
+        if (composedTileLayer.isStillValid(tile.id)) {
+            mLayerClient.beginDrawing();
+            mTileProvider.rerenderTile(tile.getImage(), tile.id.x, tile.id.y, tile.id.size, tile.id.zoom);
+            tile.invalidate();
+            Log.i(LOGTAG, "Redrawing tile " + tile.id);
+            mLayerClient.forceRedraw();
+            mLayerClient.endDrawing(mViewportMetrics);
+        }
+    }
+
+
     /** Handle the geometry change + draw. */
     private void redraw() {
         if (mLayerClient == null || mTileProvider == null) {
@@ -130,6 +142,9 @@ public class LOKitThread extends Thread implements TileProvider.TileInvalidation
             case LOEvent.TILE_REQUEST:
                 tileRequest(event.mComposedTileLayer, event.mTileId, event.mForceRedraw);
                 break;
+            case LOEvent.TILE_RERENDER:
+                tileRerender(event.mComposedTileLayer, event.mTile);
+                break;
             case LOEvent.THUMBNAIL:
                 createThumbnail(event.mTask);
         }
@@ -150,6 +165,8 @@ public class LOKitThread extends Thread implements TileProvider.TileInvalidation
 
     @Override
     public void invalidate(RectF rect) {
+        Log.i(LOGTAG, "Invalidate request: " + rect);
+
         mLayerClient = mApplication.getLayerClient();
         mLayerClient.invalidateTiles(rect);
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index ebc6927..a70b0bc 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -215,6 +215,22 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback
     }
 
     @Override
+    public void rerenderTile(CairoImage image, float x, float y, IntSize tileSize, float zoom) {
+        if (mDocument != null && image.getBuffer() != null) {
+            float twipX = pixelToTwip(x, mDPI) / zoom;
+            float twipY = pixelToTwip(y, mDPI) / zoom;
+            float twipWidth = mTileWidth / zoom;
+            float twipHeight = mTileHeight / zoom;
+
+            mDocument.paintTile(image.getBuffer(), tileSize.width, tileSize.height, (int) twipX, (int) twipY, (int) twipWidth, (int) twipHeight);
+        } else {
+            if (mDocument == null) {
+                Log.e(LOGTAG, "Document is null!!");
+            }
+        }
+    }
+
+    @Override
     public Bitmap thumbnail(int size) {
         int widthPixel = getPageWidth();
         int heightPixel = getPageHeight();
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
index 0b58f1a..16772d0 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
@@ -65,6 +65,10 @@ public class MockTileProvider implements TileProvider {
     }
 
     @Override
+    public void rerenderTile(CairoImage image, float x, float y, IntSize tileSize, float zoom) {
+    }
+
+    @Override
     public Bitmap thumbnail(int size) {
         return mLayerClient.getView().getDrawable("dummy_page");
     }
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
index abe7654..c705a94 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
@@ -16,6 +16,8 @@ public interface TileProvider {
 
     CairoImage createTile(float x, float y, IntSize tileSize, float zoom);
 
+    void rerenderTile(CairoImage image, float x, float y, IntSize tileSize, float zoom);
+
     void changePart(int partIndex);
 
     int getCurrentPartNumber();
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
index c5e7f9d..1a67117 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
@@ -213,12 +213,11 @@ public abstract class ComposedTileLayer extends Layer {
     }
 
     public void invalidateTiles(RectF rect) {
-        Log.i(LOGTAG, "invalidate: " + rect);
+        RectF zoomedRect = RectUtils.inverseScale(rect, currentZoom);
+
         for (SubTile tile : tiles) {
-            if (RectF.intersects(rect, tile.id.getRect()) || rect.contains(tile.id.getRect())) {
-                tile.markForRemoval();
-                LOKitShell.sendEvent(LOEventFactory.tileRequest(this, tile.id, true));
-                Log.i(LOGTAG, "invalidate tile: " + tile.id);
+            if (RectF.intersects(rect, tile.id.getRect())) {
+                LOKitShell.sendEvent(LOEventFactory.tileRerender(this, tile));
             }
         }
     }
commit 2755cc0f4a79b823adbc2c1a523cc2c04f0afab3
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 19:42:46 2015 +0900

    android: allow TileLayer to expose the image
    
    Change-Id: Id8968f4c71ca71d089e74314977cd406050dbd0f

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
index 9a063d0..d359502 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TileLayer.java
@@ -24,6 +24,10 @@ public abstract class TileLayer extends Layer {
 
     protected final CairoImage mImage;
 
+    public CairoImage getImage() {
+        return mImage;
+    }
+
     public enum PaintMode { NORMAL, REPEAT, STRETCH };
     private PaintMode mPaintMode;
 
commit b6a12074bcd498aa2a879dbd4e4eaa23103dad5c
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 19:39:37 2015 +0900

    android: Fix what invalidate rect numbers should mean
    
    Assumption was that the invalidate rectangle numbers from LOK
    mean (left, top, right, bottom) but they mean (width, height, x, y)
    so we need to adapt to that for now.
    
    Change-Id: Icc9c2c8aef63a8e292ff299969f2cbaf45ad0eab

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index 14a6acb..ebc6927 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -287,15 +287,15 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback
                     String[] coordinates = payload.split(",");
 
                     if (coordinates.length == 4) {
-                        int left = Integer.decode(coordinates[0].trim());
-                        int top = Integer.decode(coordinates[1].trim());
-                        int right = Integer.decode(coordinates[2].trim());
-                        int bottom = Integer.decode(coordinates[3].trim());
+                        int width = Integer.decode(coordinates[0].trim());
+                        int height = Integer.decode(coordinates[1].trim());
+                        int x = Integer.decode(coordinates[2].trim());
+                        int y = Integer.decode(coordinates[3].trim());
                         RectF rect = new RectF(
-                                twipToPixel(left, mDPI),
-                                twipToPixel(top, mDPI),
-                                twipToPixel(right, mDPI),
-                                twipToPixel(bottom, mDPI)
+                                twipToPixel(x, mDPI),
+                                twipToPixel(y, mDPI),
+                                twipToPixel(x + width, mDPI),
+                                twipToPixel(y + height, mDPI)
                         );
                         Log.i(LOGTAG, "Invalidate R: " + rect +" - " + getPageWidth() + " " + getPageHeight());
                         tileInvalidationCallback.invalidate(rect);
commit b214b0bd5271b3ab46a7317899be4b23064a6b66
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 19:35:52 2015 +0900

    android: Add inverseScale to RectUtils
    
    Change-Id: Id0e9a02614d3d6a23a8111622ae9ea49bef26f7d

diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java
index 1608e91..09168c9 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RectUtils.java
@@ -49,6 +49,14 @@ public final class RectUtils {
                          y + (rect.height() * scale));
     }
 
+    public static RectF inverseScale(RectF rect, float scale) {
+        float x = rect.left / scale;
+        float y = rect.top / scale;
+        return new RectF(x, y,
+                x + (rect.width() / scale),
+                y + (rect.height() / scale));
+    }
+
     /** Returns the nearest integer rect of the given rect. */
     public static Rect round(RectF rect) {
         Rect r = new Rect();
commit 57ffd85cbd25a28c3f70e7414ee5192b65315012
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 17:34:09 2015 +0900

    android: react to tile invalidation request and invalidate tiles
    
    Implement tile invalidation request in LOKitThread and pass the
    request to ComposedTileLayer where it handles the invalidation
    request by searching for the tiles that need to be invalidated
    (intersect the invlidation rectangle).
    
    Change-Id: I84e752486ff79e98cac1e74c6463b6748660cbed

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index b30e4f5..98b4d03 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -13,7 +13,7 @@ import org.mozilla.gecko.gfx.SubTile;
 
 import java.util.concurrent.PriorityBlockingQueue;
 
-public class LOKitThread extends Thread {
+public class LOKitThread extends Thread implements TileProvider.TileInvalidationCallback {
     private static final String LOGTAG = LOKitThread.class.getSimpleName();
 
     private PriorityBlockingQueue<LOEvent> mEventQueue = new PriorityBlockingQueue<LOEvent>();
@@ -89,6 +89,7 @@ public class LOKitThread extends Thread {
         boolean isReady = mTileProvider.isReady();
         if (isReady) {
             LOKitShell.showProgressSpinner();
+            mTileProvider.registerInvalidationCallback(this);
             refresh();
             LOKitShell.hideProgressSpinner();
         }
@@ -146,6 +147,12 @@ public class LOKitThread extends Thread {
     public void clearQueue() {
         mEventQueue.clear();
     }
+
+    @Override
+    public void invalidate(RectF rect) {
+        mLayerClient = mApplication.getLayerClient();
+        mLayerClient.invalidateTiles(rect);
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
index cfff284..c5e7f9d 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
@@ -211,4 +211,15 @@ public abstract class ComposedTileLayer extends Layer {
     public boolean isStillValid(TileIdentifier tileId) {
         return RectF.intersects(currentViewport, tileId.getRect()) || currentViewport.contains(tileId.getRect());
     }
+
+    public void invalidateTiles(RectF rect) {
+        Log.i(LOGTAG, "invalidate: " + rect);
+        for (SubTile tile : tiles) {
+            if (RectF.intersects(rect, tile.id.getRect()) || rect.contains(tile.id.getRect())) {
+                tile.markForRemoval();
+                LOKitShell.sendEvent(LOEventFactory.tileRequest(this, tile.id, true));
+                Log.i(LOGTAG, "invalidate tile: " + tile.id);
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index 09120ec..676e73c 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -488,4 +488,9 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener {
         mLowResLayer.clearAndReset();
         mRootLayer.clearAndReset();
     }
+
+    public void invalidateTiles(RectF rect) {
+        mLowResLayer.invalidateTiles(rect);
+        mRootLayer.invalidateTiles(rect);
+    }
 }
\ No newline at end of file
commit 156411e1aa39108bdf47e39dd531484a7e7db92c
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 17:31:23 2015 +0900

    android: Support force redraw in "tile request" event
    
    Change-Id: I554200f67a529e2b2c352e956372811f35f8238c

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
index cb71bb5..77ad269 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEvent.java
@@ -23,6 +23,7 @@ public class LOEvent implements Comparable<LOEvent> {
     public String mFilename;
     public TileIdentifier mTileId;
     public ComposedTileLayer mComposedTileLayer;
+    public boolean mForceRedraw;
 
     public LOEvent(int type) {
         mType = type;
@@ -33,11 +34,12 @@ public class LOEvent implements Comparable<LOEvent> {
         mTypeString = "Size Changed: " + widthPixels + " " + heightPixels;
     }
 
-    public LOEvent(int type, ComposedTileLayer composedTileLayer, TileIdentifier tileId) {
+    public LOEvent(int type, ComposedTileLayer composedTileLayer, TileIdentifier tileId, boolean forceRedraw) {
         mType = type;
         mTypeString = "Tile Request";
         mComposedTileLayer = composedTileLayer;
         mTileId = tileId;
+        mForceRedraw = forceRedraw;
     }
 
     public LOEvent(int type, String filename) {
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java
index 62c5a36..169c46e 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOEventFactory.java
@@ -29,8 +29,8 @@ public class LOEventFactory {
         return new LOEvent(LOEvent.REDRAW);
     }
 
-    public static LOEvent tileRequest(ComposedTileLayer composedTileLayer, TileIdentifier tileRequest) {
-        return new LOEvent(LOEvent.TILE_REQUEST, composedTileLayer, tileRequest);
+    public static LOEvent tileRequest(ComposedTileLayer composedTileLayer, TileIdentifier tileRequest, boolean forceRedraw) {
+        return new LOEvent(LOEvent.TILE_REQUEST, composedTileLayer, tileRequest, forceRedraw);
     }
 
     public static LOEvent thumbnail(ThumbnailCreator.ThumbnailCreationTask task) {
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
index 8fc75b2..b30e4f5 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java
@@ -26,13 +26,17 @@ public class LOKitThread extends Thread {
         TileProviderFactory.initialize();
     }
 
-    private void tileRequest(ComposedTileLayer composedTileLayer, TileIdentifier tileId) {
+    private void tileRequest(ComposedTileLayer composedTileLayer, TileIdentifier tileId, boolean forceRedraw) {
         if (composedTileLayer.isStillValid(tileId)) {
             mLayerClient.beginDrawing();
             CairoImage image = mTileProvider.createTile(tileId.x, tileId.y, tileId.size, tileId.zoom);
             SubTile tile = new SubTile(image, tileId);
             composedTileLayer.addTile(tile);
             mLayerClient.endDrawing(mViewportMetrics);
+            if (forceRedraw) {
+                Log.i(LOGTAG, "Redrawing tile " + tileId);
+                mLayerClient.forceRedraw();
+            }
         }
     }
 
@@ -123,7 +127,7 @@ public class LOKitThread extends Thread {
                 changePart(event.mPartIndex);
                 break;
             case LOEvent.TILE_REQUEST:
-                tileRequest(event.mComposedTileLayer, event.mTileId);
+                tileRequest(event.mComposedTileLayer, event.mTileId, event.mForceRedraw);
                 break;
             case LOEvent.THUMBNAIL:
                 createThumbnail(event.mTask);
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
index e6799b6..cfff284 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/ComposedTileLayer.java
@@ -165,7 +165,7 @@ public abstract class ComposedTileLayer extends Layer {
                     }
                 }
                 if (!contains) {
-                    LOEvent event = LOEventFactory.tileRequest(this, new TileIdentifier((int) x, (int) y, zoom, tileSize));
+                    LOEvent event = LOEventFactory.tileRequest(this, new TileIdentifier((int) x, (int) y, zoom, tileSize), false);
                     event.mPriority = getTilePriority();
                     LOKitShell.sendEvent(event);
                 }
commit 616a0ac18f9d373dbdb9920a63d3ce6603eedd4e
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 17:25:38 2015 +0900

    android: add toString to TileIdentifier
    
    Change-Id: Id5bfa1652a8b33757d4604e0fcf89766b50c4344

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileIdentifier.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileIdentifier.java
index fe4071c..7c51b52 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileIdentifier.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileIdentifier.java
@@ -42,4 +42,9 @@ public class TileIdentifier {
         result = 31 * result + (zoom != +0.0f ? Float.floatToIntBits(zoom) : 0);
         return result;
     }
+
+    @Override
+    public String toString() {
+        return String.format("TileIdentifier (%d, %d) z=%f s=(%d, %d)", x, y, zoom, size.width, size.height);
+    }
 }
\ No newline at end of file
commit a04e32558738c912913fa368e0e2cf237e61485c
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 17:21:01 2015 +0900

    android: Process messages in TileProvider + invalidation interface
    
    Process the LOK messages in TileProvider and add an interface to
    register and communicate invalidation requests.
    
    Change-Id: I798dc5591dbc60ee6b055a95464cd3406ecd8b0d

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
index e1aeba3..14a6acb 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java
@@ -1,6 +1,7 @@
 package org.libreoffice;
 
 import android.graphics.Bitmap;
+import android.graphics.RectF;
 import android.util.Log;
 
 import org.libreoffice.kit.Document;
@@ -13,16 +14,17 @@ import org.mozilla.gecko.gfx.IntSize;
 
 import java.nio.ByteBuffer;
 
-public class LOKitTileProvider implements TileProvider {
+public class LOKitTileProvider implements TileProvider, Document.MessageCallback {
     private static final String LOGTAG = LOKitTileProvider.class.getSimpleName();
     private static int TILE_SIZE = 256;
-    private Office mOffice;
-    private Document mDocument;
     private final GeckoLayerClient mLayerClient;
     private final float mTileWidth;
     private final float mTileHeight;
     private final String mInputFile;
+    private Office mOffice;
+    private Document mDocument;
     private boolean mIsReady = false;
+    private TileInvalidationCallback tileInvalidationCallback = null;
 
     private float mDPI;
     private float mWidthTwip;
@@ -67,6 +69,7 @@ public class LOKitTileProvider implements TileProvider {
 
     public void postLoad() {
         mDocument.initializeForRendering();
+        mDocument.setMessageCallback(this);
 
         int parts = mDocument.getParts();
         Log.i(LOGTAG, "Document parts: " + parts);
@@ -254,6 +257,12 @@ public class LOKitTileProvider implements TileProvider {
     }
 
     @Override
+    public void registerInvalidationCallback(TileInvalidationCallback tileInvalidationCallback) {
+        this.tileInvalidationCallback = tileInvalidationCallback;
+    }
+
+
+    @Override
     protected void finalize() throws Throwable {
         close();
         super.finalize();
@@ -269,6 +278,31 @@ public class LOKitTileProvider implements TileProvider {
     public int getCurrentPartNumber() {
         return mDocument.getPart();
     }
+
+    @Override
+    public void messageRetrieved(int signalNumber, String payload) {
+        switch (signalNumber) {
+            case 0:
+                if (!payload.equals("EMPTY")) {
+                    String[] coordinates = payload.split(",");
+
+                    if (coordinates.length == 4) {
+                        int left = Integer.decode(coordinates[0].trim());
+                        int top = Integer.decode(coordinates[1].trim());
+                        int right = Integer.decode(coordinates[2].trim());
+                        int bottom = Integer.decode(coordinates[3].trim());
+                        RectF rect = new RectF(
+                                twipToPixel(left, mDPI),
+                                twipToPixel(top, mDPI),
+                                twipToPixel(right, mDPI),
+                                twipToPixel(bottom, mDPI)
+                        );
+                        Log.i(LOGTAG, "Invalidate R: " + rect +" - " + getPageWidth() + " " + getPageHeight());
+                        tileInvalidationCallback.invalidate(rect);
+                    }
+                }
+        }
+    }
 }
 
 // vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
index 79fef43..0b58f1a 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java
@@ -79,6 +79,10 @@ public class MockTileProvider implements TileProvider {
     }
 
     @Override
+    public void registerInvalidationCallback(TileInvalidationCallback tileInvalidationCallback) {
+    }
+
+    @Override
     public void changePart(int partIndex) {
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
index 988e53a..abe7654 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProvider.java
@@ -2,6 +2,7 @@ package org.libreoffice;
 
 
 import android.graphics.Bitmap;
+import android.graphics.RectF;
 
 import org.mozilla.gecko.gfx.CairoImage;
 import org.mozilla.gecko.gfx.IntSize;
@@ -24,4 +25,10 @@ public interface TileProvider {
     void close();
 
     boolean isTextDocument();
+
+    void registerInvalidationCallback(TileProvider.TileInvalidationCallback tileInvalidationCallback);
+
+    public interface TileInvalidationCallback {
+        void invalidate(RectF rect);
+    }
 }
commit e905d3b3e9eb356b26fc4d860a0fbdcd5d041092
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri Jan 9 17:15:42 2015 +0900

    android: interface for processing of LOK messages
    
    Added a message callback interface to Document where the provided
    implementation processes the messages from LOK (for now
    only the regions that were invalidated)
    
    Change-Id: Ic7fcb0250f87f6c4c28925bf809c4cf3f353d2bb

diff --git a/android/Bootstrap/src/org/libreoffice/kit/Document.java b/android/Bootstrap/src/org/libreoffice/kit/Document.java
index 6985a7c..10d0a0c 100644
--- a/android/Bootstrap/src/org/libreoffice/kit/Document.java
+++ b/android/Bootstrap/src/org/libreoffice/kit/Document.java
@@ -27,18 +27,25 @@ public class Document {
     public static final int DOCTYPE_OTHER = 4;
 
     private final ByteBuffer handle;
+    private MessageCallback messageCallback = null;
 
     public Document(ByteBuffer handle) {
         this.handle = handle;
         bindMessageCallback();
     }
 
+    public void setMessageCallback(MessageCallback messageCallback) {
+        this.messageCallback = messageCallback;
+    }
+
     /**
      * Callback triggered through JNI to indicate that a new singal
      * from LibreOfficeKit was retrieved.
      */
     private void messageRetrieved(int signalNumber, String payload) {
-        Log.i("Document", "Signal retrieved: " + signalNumber + " " + payload);
+        if (messageCallback != null) {
+            messageCallback.messageRetrieved(signalNumber, payload);
+        }
     }
 
     /**
@@ -78,4 +85,8 @@ public class Document {
 
     public native void initializeForRendering();
 
+    public interface MessageCallback {
+        void messageRetrieved(int signalNumber, String payload);
+    }
+
 }
commit 160e3c603c642e1b12a03bddb32ce0ef68e52665
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Jan 8 17:14:28 2015 +0100

    gtktiledviewer: invoke lok::Office::postKeyEvent() on key press / release
    
    Change-Id: I82587fb48f5b7d037d66c0eb0e4aa1c7cee8702a

diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
index bb3c28a..c4725f2 100644
--- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
@@ -125,8 +125,14 @@ void changeQuadView( GtkWidget* /*pButton*/, gpointer /* pItem */ )
 }
 
 /// Receives a key press or release event.
-static void signalKey(GtkWidget* /*pWidget*/, GdkEventKey* /*pEvent*/, gpointer /*pData*/)
+static void signalKey(GtkWidget* /*pWidget*/, GdkEventKey* pEvent, gpointer /*pData*/)
 {
+    LOKDocView* pLOKDocView = LOK_DOCVIEW(pDocView);
+
+    if (pEvent->type == GDK_KEY_RELEASE)
+        pLOKDocView->pOffice->pClass->postKeyEvent(pLOKDocView->pOffice, 1, gdk_keyval_to_unicode(pEvent->keyval));
+    else
+        pLOKDocView->pOffice->pClass->postKeyEvent(pLOKDocView->pOffice, 0, gdk_keyval_to_unicode(pEvent->keyval));
 }
 
 // GtkComboBox requires gtk 2.24 or later
commit 8de39435246176ed3eb603c177c8c3d26f9027b9
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Jan 8 17:13:20 2015 +0100

    Add lok::Office::postKeyEvent()
    
    Change-Id: Ib80a8dd433b22a5e88aaab8e11d5c42ced8097ae

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 08a353f..c3eedf5 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -54,6 +54,7 @@
 #if defined(UNX) && !defined(MACOSX) && !defined(ENABLE_HEADLESS)
 // And let's also grab the SvpSalInstance and SvpSalVirtualDevice
 #include <headless/svpinst.hxx>
+#include <headless/svpframe.hxx>
 #include <headless/svpvd.hxx>
 
 #include <basebmp/bitmapdevice.hxx>
@@ -251,6 +252,8 @@ static void                    lo_destroy       (LibreOfficeKit* pThis);
 static int                     lo_initialize    (LibreOfficeKit* pThis, const char* pInstallPath);
 static LibreOfficeKitDocument* lo_documentLoad  (LibreOfficeKit* pThis, const char* pURL);
 static char *                  lo_getError      (LibreOfficeKit* pThis);
+static void                    lo_postKeyEvent  (LibreOfficeKit* pThis, int nType, int nCode);
+
 
 struct LibLibreOffice_Impl : public _LibreOfficeKit
 {
@@ -268,6 +271,7 @@ struct LibLibreOffice_Impl : public _LibreOfficeKit
             m_pOfficeClass->destroy = lo_destroy;
             m_pOfficeClass->documentLoad = lo_documentLoad;
             m_pOfficeClass->getError = lo_getError;
+            m_pOfficeClass->postKeyEvent = lo_postKeyEvent;
 
             gOfficeClass = m_pOfficeClass;
         }
@@ -647,6 +651,20 @@ static char* lo_getError (LibreOfficeKit *pThis)
     return pMemory;
 }
 
+static void lo_postKeyEvent(LibreOfficeKit* /*pThis*/, int nType, int nCode)
+{
+#if defined(UNX) && !defined(MACOSX) && !defined(ENABLE_HEADLESS)
+    if (SalFrame *pFocus = SvpSalFrame::GetFocusFrame())
+    {
+        KeyEvent aEvent(nCode, nCode, 0);
+        if (nType == 0)
+            Application::PostKeyEvent(VCLEVENT_WINDOW_KEYINPUT, pFocus->GetWindow(), &aEvent);
+        else
+            Application::PostKeyEvent(VCLEVENT_WINDOW_KEYUP, pFocus->GetWindow(), &aEvent);
+    }
+#endif
+}
+
 static void force_c_locale(void)
 {
     // force locale (and resource files loaded) to en-US
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 573e44d..d4c1f99 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -79,6 +79,7 @@ struct _LibreOfficeKitClass
   void                    (*destroy)       (LibreOfficeKit* pThis);
   LibreOfficeKitDocument* (*documentLoad)  (LibreOfficeKit* pThis, const char* pURL);
   char*                   (*getError)      (LibreOfficeKit* pThis);
+  void                    (*postKeyEvent)  (LibreOfficeKit* pThis, int nType, int nCode);
 };
 
 #define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize)
@@ -143,6 +144,9 @@ struct _LibreOfficeKitDocumentClass
   void (*registerCallback)   (LibreOfficeKitDocument* pThis,
                               LibreOfficeKitCallback pCallback,
                               void* pData);
+  void (*postKeyEvent) (LibreOfficeKitDocument* pThis,
+                        int nType,
+                        int nCode);
 #endif // LOK_USE_UNSTABLE_API
 };
 
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index 2a57232..fdc025b 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -135,6 +135,17 @@ public:
     {
         return mpThis->pClass->getError(mpThis);
     }
+
+    /**
+     * Posts a keyboard event to the focused frame.
+     *
+     * @param nType Event type, like press or release.
+     * @param nCode Code of the key.
+     */
+    inline void postKeyEvent(int nType, int nCode)
+    {
+        mpThis->pClass->postKeyEvent(mpThis, nType, nCode);
+    }
 };
 
 inline Office* lok_cpp_init(const char* pInstallPath)
diff --git a/vcl/inc/headless/svpframe.hxx b/vcl/inc/headless/svpframe.hxx
index d2a786c..85e5f6b 100644
--- a/vcl/inc/headless/svpframe.hxx
+++ b/vcl/inc/headless/svpframe.hxx
@@ -58,7 +58,7 @@ class SvpSalFrame : public SalFrame
 
     std::list< SvpSalGraphics* >        m_aGraphics;
 
-    static SvpSalFrame*       s_pFocusFrame;
+    SAL_DLLPUBLIC_EXPORT static SvpSalFrame*       s_pFocusFrame;
 public:
     SvpSalFrame( SvpSalInstance* pInstance,
                  SalFrame* pParent,
@@ -137,7 +137,7 @@ public:
     virtual void                SetApplicationID(const OUString &rApplicationID) SAL_OVERRIDE { (void) rApplicationID; }
     bool                        IsVisible() { return m_bVisible; }
 
-    static SvpSalFrame*         GetFocusFrame() { return s_pFocusFrame; }
+    SAL_DLLPUBLIC_EXPORT static SvpSalFrame*         GetFocusFrame() { return s_pFocusFrame; }
 
 };
 
commit 8d8729cecd3b1707c936873ec02c9fbca3c66cf2
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Jan 8 10:13:54 2015 +0100

    gtktiledviewer: react to key releases
    
    Change-Id: I5cbbd482fcf2e36851e1f82efc1cd511d856d10b

diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
index 6aea0f8..bb3c28a 100644
--- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
@@ -124,8 +124,8 @@ void changeQuadView( GtkWidget* /*pButton*/, gpointer /* pItem */ )
     }
 }
 
-/// Receives a key press event.
-static void docViewKeyPress(GtkWidget* /*pWidget*/, GdkEvent* /*pEvent*/, gpointer /*pData*/)
+/// Receives a key press or release event.
+static void signalKey(GtkWidget* /*pWidget*/, GdkEventKey* /*pEvent*/, gpointer /*pData*/)
 {
 }
 
@@ -284,7 +284,8 @@ int main( int argc, char* argv[] )
     pDocViewQuad = 0;
 
     // Input handling.
-    g_signal_connect(pWindow, "key-press-event", G_CALLBACK(docViewKeyPress), NULL);
+    g_signal_connect(pWindow, "key-press-event", G_CALLBACK(signalKey), NULL);
+    g_signal_connect(pWindow, "key-release-event", G_CALLBACK(signalKey), NULL);
 
     gtk_container_add( GTK_CONTAINER(pVBox), pDocView );
 
commit 92e350866c024710e830ca03489e81d64e0e7303
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Jan 7 17:19:40 2015 +0100

    gtktiledviewer: react to key presses
    
    Change-Id: Ic9226bc0118482b381eff8d5d777e01c293c4deb

diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
index 8f804f0..6aea0f8 100644
--- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
@@ -124,6 +124,11 @@ void changeQuadView( GtkWidget* /*pButton*/, gpointer /* pItem */ )
     }
 }
 
+/// Receives a key press event.
+static void docViewKeyPress(GtkWidget* /*pWidget*/, GdkEvent* /*pEvent*/, gpointer /*pData*/)
+{
+}
+
 // GtkComboBox requires gtk 2.24 or later
 #if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
 void populatePartSelector()
@@ -277,6 +282,10 @@ int main( int argc, char* argv[] )
     // Docview
     pDocView = lok_docview_new( pOffice );
     pDocViewQuad = 0;
+
+    // Input handling.
+    g_signal_connect(pWindow, "key-press-event", G_CALLBACK(docViewKeyPress), NULL);
+
     gtk_container_add( GTK_CONTAINER(pVBox), pDocView );
 
     gtk_widget_show_all( pWindow );
commit 057fb145f13a85095fd296731a17ba95483d4434
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Jan 7 16:07:55 2015 +0100

    LibreOfficeKitGtk: lok_docview is never read
    
    Change-Id: Ibb7a6dd46541afe8908b108450e64b91c8830026

diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h
index 522d74d..111381d 100644
--- a/include/LibreOfficeKit/LibreOfficeKitGtk.h
+++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h
@@ -46,8 +46,6 @@ struct _LOKDocView
 struct _LOKDocViewClass
 {
   GtkScrolledWindowClass parent_class;
-
-  void (*lok_docview) (LOKDocView* pDocView);
 };
 
 guint           lok_docview_get_type        (void);
diff --git a/libreofficekit/source/gtk/lokdocview.c b/libreofficekit/source/gtk/lokdocview.c
index 4e13f03..903f7e3 100644
--- a/libreofficekit/source/gtk/lokdocview.c
+++ b/libreofficekit/source/gtk/lokdocview.c
@@ -52,7 +52,7 @@ SAL_DLLPUBLIC_EXPORT guint lok_docview_get_type()
 
 static void lok_docview_class_init( LOKDocViewClass* pClass )
 {
-    pClass->lok_docview = NULL;
+    (void)pClass;
 }
 
 static void lok_docview_init( LOKDocView* pDocView )
commit 3b77cd3bbd12c6ac145fb3887f3428e2fc6a39e6
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Jan 7 19:37:53 2015 +0900

    android: Add support for callbacks from LO to JNI and Java LOK
    
    This adds support to retrieve callbacks from LibreOffice (like
    for example that a part of document has been invalidated) to
    LibreOfficeKit JNI and Java wrappers.
    
    Change-Id: Ib70187194d002c72b64d58032aab216adc591565

diff --git a/android/Bootstrap/src/org/libreoffice/kit/Document.java b/android/Bootstrap/src/org/libreoffice/kit/Document.java
index e415d8f..6985a7c 100644
--- a/android/Bootstrap/src/org/libreoffice/kit/Document.java
+++ b/android/Bootstrap/src/org/libreoffice/kit/Document.java
@@ -9,6 +9,8 @@
 
 package org.libreoffice.kit;
 
+import android.util.Log;
+
 import java.nio.ByteBuffer;
 
 public class Document {
@@ -28,8 +30,22 @@ public class Document {
 
     public Document(ByteBuffer handle) {
         this.handle = handle;
+        bindMessageCallback();
+    }
+
+    /**
+     * Callback triggered through JNI to indicate that a new singal
+     * from LibreOfficeKit was retrieved.
+     */
+    private void messageRetrieved(int signalNumber, String payload) {
+        Log.i("Document", "Signal retrieved: " + signalNumber + " " + payload);
     }
 
+    /**
+     * Bind the signal callback in LOK.
+     */
+    private native void bindMessageCallback();
+
     public native void destroy();
 
     public native int getPart();
diff --git a/desktop/source/lib/lokandroid.cxx b/desktop/source/lib/lokandroid.cxx
index 2b18071..06da8a9 100644
--- a/desktop/source/lib/lokandroid.cxx
+++ b/desktop/source/lib/lokandroid.cxx
@@ -22,6 +22,9 @@
 
 /* LibreOfficeKit */
 
+namespace
+{
+
 jfieldID getHandleField(JNIEnv* pEnv, jobject aObject)
 {
     jclass clazz = pEnv->GetObjectClass(aObject);
@@ -46,6 +49,8 @@ const char* copyJavaString(JNIEnv* pEnv, jstring aJavaString)
     return pClone;
 }
 
+} // anonymous namespace
+
 extern "C" SAL_JNI_EXPORT jstring JNICALL Java_org_libreoffice_kit_Office_getError(JNIEnv* pEnv, jobject aObject)
 {
     LibreOfficeKit* pLibreOfficeKit = getHandle<LibreOfficeKit>(pEnv, aObject);
@@ -68,6 +73,55 @@ extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Office_destroyAn
     _exit(0);
 }
 
+namespace
+{
+
+struct CallbackData
+{
+    jmethodID aJavaCallbackMethod;
+    jclass aClass;
+    jobject aObject;
+};
+
+static CallbackData gCallbackData;
+
+/**
+ * Handle retrieved callback
+ */
+void messageCallback(int nType, const char* pPayload, void* pData)
+{
+    CallbackData* pCallbackData = (CallbackData*) pData;
+
+    JavaVM* pJavaVM = lo_get_javavm();
+    JNIEnv* pEnv;
+    bool bIsAttached = false;
+
+    int status = pJavaVM->GetEnv((void **) &pEnv, JNI_VERSION_1_6);
+
+    if(status < 0)
+    {
+        status = pJavaVM->AttachCurrentThread(&pEnv, NULL);
+        if(status < 0)
+        {
+            return;
+        }
+        bIsAttached = true;
+    }
+
+    jvalue aParameter[2];
+    aParameter[0].i = nType;
+    aParameter[1].l = pEnv->NewStringUTF(pPayload);
+
+    pEnv->CallVoidMethodA(pCallbackData->aObject, pCallbackData->aJavaCallbackMethod, aParameter);
+
+    if (bIsAttached)
+    {
+        pJavaVM->DetachCurrentThread();
+    }
+}
+
+} // anonymous namespace
+
 extern "C" SAL_JNI_EXPORT jobject JNICALL Java_org_libreoffice_kit_Office_documentLoadNative(JNIEnv* pEnv, jobject aObject, jstring documentPath)
 {
     const char* aCloneDocumentPath = copyJavaString(pEnv, documentPath);
@@ -81,6 +135,21 @@ extern "C" SAL_JNI_EXPORT jobject JNICALL Java_org_libreoffice_kit_Office_docume
 
 /* Document */
 
+/** Implementation of org.libreoffice.kit.Document.bindMessageCallback method */
+extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Document_bindMessageCallback
+    (JNIEnv* pEnv, jobject aObject)
+{
+    LibreOfficeKitDocument* pDocument = getHandle<LibreOfficeKitDocument>(pEnv, aObject);
+
+    gCallbackData.aObject = (jobject) pEnv->NewGlobalRef(aObject);
+    jclass aClass = pEnv->GetObjectClass(aObject);
+    gCallbackData.aClass = (jclass) pEnv->NewGlobalRef(aClass);
+
+    gCallbackData.aJavaCallbackMethod = pEnv->GetMethodID(aClass, "messageRetrieved", "(ILjava/lang/String;)V");
+
+    pDocument->pClass->registerCallback(pDocument, messageCallback, (void*) &gCallbackData);
+}
+
 extern "C" SAL_JNI_EXPORT void JNICALL Java_org_libreoffice_kit_Document_destroy
     (JNIEnv* pEnv, jobject aObject)
 {
commit 0dbc6f5689541fab86b216e6a0be3a4c7ffcadfe
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Jan 7 19:05:05 2015 +0900

    android: No reason to return JNI version less than Java 6
    
    Change-Id: Id9fae6561268bb7e5a465c19bdb80124f94f4939

diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c
index 2d2f01a..4d318e8 100644
--- a/sal/android/lo-bootstrap.c
+++ b/sal/android/lo-bootstrap.c
@@ -247,7 +247,7 @@ JNI_OnLoad(JavaVM* vm, void* reserved)
 
     the_java_vm = vm;
 
-    return JNI_VERSION_1_2;
+    return JNI_VERSION_1_6;
 }
 
 // public static native boolean setup(String dataDir,
commit 27a644b3b029d19fb2ed38201de92fe5fd9d9e5f
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Jan 7 19:02:16 2015 +0900

    lok: Add comments to some methods, put the star where it belongs
    
    Change-Id: I751eb175f29489637f465c9d97ebe920372f38bf

diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index a4addb8..573e44d 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -76,9 +76,9 @@ struct _LibreOfficeKitClass
 {
   size_t  nSize;
 
-  void                    (*destroy)       (LibreOfficeKit *pThis);
-  LibreOfficeKitDocument* (*documentLoad)  (LibreOfficeKit *pThis, const char *pURL);
-  char*                   (*getError)      (LibreOfficeKit *pThis);
+  void                    (*destroy)       (LibreOfficeKit* pThis);
+  LibreOfficeKitDocument* (*documentLoad)  (LibreOfficeKit* pThis, const char* pURL);
+  char*                   (*getError)      (LibreOfficeKit* pThis);
 };
 
 #define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize)
@@ -94,16 +94,20 @@ struct _LibreOfficeKitDocumentClass
 
   void (*destroy)   (LibreOfficeKitDocument* pThis);
   int (*saveAs)     (LibreOfficeKitDocument* pThis,
-                     const char *pUrl,
-                     const char *pFormat,
-                     const char *pFilterOptions);
+                     const char* pUrl,
+                     const char* pFormat,
+                     const char* pFilterOptions);
 #ifdef LOK_USE_UNSTABLE_API
   LibreOfficeKitDocumentType (*getDocumentType) (LibreOfficeKitDocument* pThis);
 
-  // Part refers to either indivual sheets in a Spreadsheet, or slides
-  // in a Slideshow, and has no relevance for writer documents.
+  /** Get number of part that the document contains.
+   * Part refers to either indivual sheets in a Spreadsheet,
+   * or slides in a Slideshow, and has no relevance for
+   * writer documents.
+   */
   int (*getParts) (LibreOfficeKitDocument* pThis);
 
+  /** Get current part of the document */
   int (*getPart)          (LibreOfficeKitDocument* pThis);
   void (*setPart)         (LibreOfficeKitDocument* pThis,
                            int nPart);
@@ -124,12 +128,16 @@ struct _LibreOfficeKitDocumentClass
                            const int nTileWidth,
                            const int nTileHeight);
 
-  // Get the document sizes in twips.
+  /** Get the document sizes in twips. */
   void (*getDocumentSize) (LibreOfficeKitDocument* pThis,
                            long* pWidth,
                            long* pHeight);
 
-  // Initialize document for rendering.
+  /** Initialize document for rendering.
+   * Sets the rendering and document parameters to default values
+   * that are needed to render the document correctly using
+   * tiled rendering.
+   */
   void (*initializeForRendering) (LibreOfficeKitDocument* pThis);
 
   void (*registerCallback)   (LibreOfficeKitDocument* pThis,


More information about the Libreoffice-commits mailing list