[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-4' - 289 commits - android/app android/build.gradle android/.gitignore android/gradle.properties android/gradlew android/gradlew.bat android/lib android/Makefile.am android/README android/settings.gradle android/templates bundled/include common/Log.hpp common/MessageQueue.cpp common/MessageQueue.hpp common/Protocol.hpp common/Session.cpp common/Session.hpp common/SigUtil.cpp common/Unit.cpp common/Unit.hpp common/Util.cpp configure.ac discovery.xml docker/Dockerfile docker/docker-nightly.sh docker/l10n-docker-nightly.sh docker/scripts .gitignore gtk/Makefile.am ios/config.h.in ios/ios.mm ios/Mobile ios/Mobile.xcodeproj ios/README kit/ChildSession.cpp kit/ChildSession.hpp kit/Kit.cpp kit/KitHelper.hpp kit/Kit.hpp loleaflet/admin loleaflet/build loleaflet/css loleaflet/html loleaflet/images loleaflet/js loleaflet/l10n loleaflet/Makefile.am loleaflet/plugins loleaflet/reference.html loleaflet/src loleaflet/util loolwsd.xml.i n Makefile.am Mobile/Android net/FakeSocket.cpp net/ServerSocket.hpp net/Socket.cpp net/Socket.hpp net/WebSocketHandler.hpp scripts/downloadpootle.sh scripts/unocommands.py test/data test/httpwstest.cpp test/Makefile.am test/run_unit.sh.in test/TileCacheTests.cpp test/UnitHTTP.cpp test/UnitTileCache.cpp test/UnitWOPITemplate.cpp test/WhiteBoxTests.cpp tools/KitClient.cpp wsd/Admin.cpp wsd/AdminModel.cpp wsd/AdminModel.hpp wsd/ClientSession.cpp wsd/ClientSession.hpp wsd/DocumentBroker.cpp wsd/DocumentBroker.hpp wsd/LOOLWSD.cpp wsd/LOOLWSD.hpp wsd/reference.md wsd/Storage.cpp wsd/Storage.hpp wsd/TileCache.cpp wsd/TileCache.hpp wsd/TileDesc.hpp wsd/TraceFile.hpp

Tor Lillqvist (via logerrit) logerrit at kemper.freedesktop.org
Tue Oct 1 05:53:38 UTC 2019


Rebased ref, commits from common ancestor:
commit bd8b8f6fa8df2c8bd3bec15d3086ce6e2e44a212
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Mon Sep 30 23:46:09 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Tue Oct 1 07:53:17 2019 +0200

    Factor out the FakeSocketPair creation from fakeSocketSocket()
    
    Avoids misleading duplicate logging from fakeSocketPipe2().
    
    Change-Id: Iaf0f2e621d25cbe869b7c5f3db0fbf36064f96cd
    Reviewed-on: https://gerrit.libreoffice.org/79901
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/net/FakeSocket.cpp b/net/FakeSocket.cpp
index c31f6c0b8..1f0bbe780 100644
--- a/net/FakeSocket.cpp
+++ b/net/FakeSocket.cpp
@@ -102,7 +102,7 @@ void fakeSocketSetLoggingCallback(void (*callback)(const std::string&))
     loggingCallback = callback;
 }
 
-int fakeSocketSocket()
+static int fakeSocketAllocate()
 {
     std::vector<FakeSocketPair>& fds = getFds();
 
@@ -119,14 +119,21 @@ int fakeSocketSocket()
 
     result.fd[0] = i*2;
 
-    FAKESOCKET_LOG("FakeSocket Create #" << i*2 << flush());
-
     return i*2;
 }
 
+int fakeSocketSocket()
+{
+    const int result = fakeSocketAllocate();
+
+    FAKESOCKET_LOG("FakeSocket Create #" << result << flush());
+
+    return result;
+}
+
 int fakeSocketPipe2(int pipefd[2])
 {
-    pipefd[0] = fakeSocketSocket();
+    pipefd[0] = fakeSocketAllocate();
     assert(pipefd[0] >= 0);
 
     std::vector<FakeSocketPair>& fds = getFds();
commit 4e0341fe056300990ab7cca02fd9b9e718f22cb5
Author:     Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Mon Sep 30 13:42:43 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Mon Sep 30 14:06:39 2019 +0200

    Fix up TileCacheTests::testTileInvalidateWriterPage() test
    
    The part number in case of writer has no actual meaning, since
    for writer we have only one part (the whole document).
    It seems the code is not consistent in that it is 0 or 1.
    
    Change-Id: I9e56079f7861f7e0d5794e6f711045cd9448dfa7
    Reviewed-on: https://gerrit.libreoffice.org/79851
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>

diff --git a/test/TileCacheTests.cpp b/test/TileCacheTests.cpp
index 5f9a8aae8..b4ec0fa8d 100644
--- a/test/TileCacheTests.cpp
+++ b/test/TileCacheTests.cpp
@@ -815,7 +815,7 @@ void TileCacheTests::testTileInvalidateWriterPage()
     int part = -1;
     CPPUNIT_ASSERT_MESSAGE("No part# in invalidatetiles message.",
                            LOOLProtocol::getTokenIntegerFromMessage(res, "part", part));
-    CPPUNIT_ASSERT_EQUAL(1, part);
+    CPPUNIT_ASSERT_EQUAL(0, part);
 }
 
 // This isn't yet used
commit b58e781a7c679db732c56fc3fe013b9656a19bd3
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Sat Sep 14 14:11:23 2019 +0200
Commit:     Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Mon Sep 30 14:06:34 2019 +0200

    Remove invalidations triggered by LOK_CALLBACK_DOCUMENT_SIZE_CHANGED
    
    (cherry picked from commit 53cd0a50a6e565c08295acb54f16ec08af7c31af)
    
    Change-Id: I337471cdfdaa1f9b49f13bcb05340427f116cac0
    Reviewed-on: https://gerrit.libreoffice.org/79716
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    Tested-by: Tamás Zolnai <tamas.zolnai at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/79849

diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index 40a06c0e4..d0029fb71 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -2138,22 +2138,7 @@ void ChildSession::loKitCallback(const int type, const std::string& payload)
         sendTextFrame("searchresultselection: " + payload);
         break;
     case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
-        {
-            //TODO: clenaup and merge.
-
-            const int parts = getLOKitDocument()->getParts();
-            for (int i = 0; i < parts; ++i)
-            {
-                sendTextFrame("invalidatetiles:"
-                              " part=" + std::to_string(i) +
-                              " x=0" +
-                              " y=0" +
-                              " width=" + std::to_string(INT_MAX) +
-                              " height=" + std::to_string(INT_MAX));
-            }
-
-            getStatus("", 0);
-        }
+        getStatus("", 0);
         break;
     case LOK_CALLBACK_SET_PART:
         sendTextFrame("setpart: " + payload);
commit 6500306e628ff20c7f1d97b9f97cdf46c45168f6
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Fri Sep 27 10:41:24 2019 +0200
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Fri Sep 27 14:42:47 2019 +0200

    tdf#125567 add menu option to trigger spelling dialog in impress/calc
    
    Change-Id: Ia80151969d8d1158c0fd9cb60c7fe238647f7a39
    Reviewed-on: https://gerrit.libreoffice.org/79680
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 8091cc8ff67184facb9e71a33499cda370334615)
    Reviewed-on: https://gerrit.libreoffice.org/79684
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index 7efdfe27b..e3af7e8fa 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -318,6 +318,7 @@ L.Control.Menubar = L.Control.extend({
 				{name: _('Fullscreen presentation'), id: 'fullscreen-presentation', type: 'action'}]
 			},
 			{name: _UNO('.uno:ToolsMenu', 'presentation'), id: 'tools', type: 'menu', menu: [
+				{uno: '.uno:SpellDialog'},
 				{uno: '.uno:SpellOnline'},
 				{name: _UNO('.uno:LanguageMenu'), type: 'menu', menu: [
 					{name: _('None (Do not check spelling)'), id: 'nonelanguage', uno: '.uno:LanguageStatus?Language:string=Default_LANGUAGE_NONE'}]}
@@ -431,6 +432,7 @@ L.Control.Menubar = L.Control.extend({
 					{uno: '.uno:ShowDetail'}]}
 			]},
 			{name: _UNO('.uno:ToolsMenu', 'spreadsheet'), id: 'tools', type: 'menu', menu: [
+				{uno: '.uno:SpellDialog'},
 				{uno: '.uno:SpellOnline'},
 				{name: _UNO('.uno:LanguageMenu'), type: 'menu', menu: [
 					{name: _('None (Do not check spelling)'), id: 'nonelanguage', uno: '.uno:LanguageStatus?Language:string=Default_LANGUAGE_NONE'}]},
diff --git a/loleaflet/src/unocommands.js b/loleaflet/src/unocommands.js
index 7812790ac..ac7346a3d 100644
--- a/loleaflet/src/unocommands.js
+++ b/loleaflet/src/unocommands.js
@@ -34,7 +34,7 @@ var unoCommandsArray = {
 	CondDateFormatDialog:{spreadsheet:{menu:_('Date...'),},},
 	ConditionalFormatDialog:{spreadsheet:{menu:_('Condition...'),},},
 	ConditionalFormatManagerDialog:{spreadsheet:{menu:_('Manage...'),},},
-	ConditionalFormatMenu:{spreadsheet:{menu:_('C~onditional'),},},
+	ConditionalFormatMenu:{spreadsheet:{menu:_('C~onditional Formatting'),},},
 	ContinueNumbering:{text:{menu:_('Continue previous numbering'),},},
 	ControlCodes:{text:{menu:_('For~matting Marks'),},},
 	Copy:{global:{menu:_('~Copy'),},},
@@ -227,6 +227,7 @@ var unoCommandsArray = {
 	SpacePara1:{global:{menu:_('Line Spacing: 1'),},},
 	SpacePara15:{global:{menu:_('Line Spacing: 1.5'),},},
 	SpacePara2:{global:{menu:_('Line Spacing: 2'),},},
+	SpellDialog:{global:{menu:_('~Spelling...'),},},
 	SpellOnline:{global:{menu:_('~Automatic Spell Checking'),},},
 	SpellingAndGrammarDialog:{global:{menu:_('~Spelling...'),},},
 	SplitCell:{presentation:{menu:_('Split Cells'),},spreadsheet:{menu:_('Split Cells'),},text:{menu:_('Split Cells...'),},},
commit d7813989913e95cefc8484d6d2af965ed5752588
Author:     Andras Timar <andras.timar at collabora.com>
AuthorDate: Fri Sep 27 12:56:32 2019 +0200
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Fri Sep 27 13:33:37 2019 +0200

    Remove Lotus WordPro support
    
    ... because lotuswordpro filter is not present in MPLv2-only core builds
    
    Change-Id: I100e886273f8b7fd38887576c2d29fad4c69b2e7
    Reviewed-on: https://gerrit.libreoffice.org/79683
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/discovery.xml b/discovery.xml
index 517485642..13ee6ef0d 100644
--- a/discovery.xml
+++ b/discovery.xml
@@ -1,9 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <wopi-discovery>
     <net-zone name="external-http">
-        <app name="application/vnd.lotus-wordpro">
-            <action name="view" ext="lwp"/>
-        </app>
         <app name="image/svg+xml">
             <action name="view" ext="svg"/>
         </app>
diff --git a/ios/Mobile/Info.plist.in b/ios/Mobile/Info.plist.in
index a3a8b2e51..66f4bd375 100644
--- a/ios/Mobile/Info.plist.in
+++ b/ios/Mobile/Info.plist.in
@@ -284,20 +284,6 @@
             <key>CFBundleTypeIconFiles</key>
             <array/>
             <key>CFBundleTypeName</key>
-            <string>Lotus WordPro Document</string>
-            <key>CFBundleTypeRole</key>
-            <string>Viewer</string>
-            <key>LSHandlerRank</key>
-            <string>Alternate</string>
-            <key>LSItemContentTypes</key>
-            <array>
-                <string>com.collabora.office.uti.lwp</string>
-            </array>
-        </dict>
-        <dict>
-            <key>CFBundleTypeIconFiles</key>
-            <array/>
-            <key>CFBundleTypeName</key>
             <string>Plain Text</string>
             <key>CFBundleTypeRole</key>
             <string>Editor</string>
@@ -487,21 +473,6 @@
                 <string>public.data</string>
             </array>
             <key>UTTypeDescription</key>
-            <string>Lotus WordPro Document</string>
-            <key>UTTypeIdentifier</key>
-            <string>com.collabora.office.uti.lwp</string>
-            <key>UTTypeTagSpecification</key>
-            <dict>
-                <key>public.filename-extension</key>
-                <string>lwp</string>
-            </dict>
-        </dict>
-        <dict>
-            <key>UTTypeConformsTo</key>
-            <array>
-                <string>public.data</string>
-            </array>
-            <key>UTTypeDescription</key>
             <string>OpenDocument Spreadsheet</string>
             <key>UTTypeIconFiles</key>
             <array/>
commit ee497b873eadfa3ab4ba77793748e83ff649dacf
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Thu Sep 26 17:39:41 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Thu Sep 26 17:51:44 2019 +0200

    tdf#125575: Must reset the "kit" callback to null when closing document
    
    As we register the global "kit" callback with the Document object
    pointer as callback data, we must unregister it when the document is
    being "unloaded" and the Document object will destruct shortly.
    Otherwise the callback might be called for the next document with a
    stale pointer.
    
    Relevant only for the iOS app, and presumably the Android one. In
    web-based Online, the kit process will exit anyway after the document
    is closed. But in an app there is just one process that keeps running
    for a long time handling all documents that are edited.
    
    For some reason the crash only showed up when a document was created
    from a template, closed, and another document was created from a
    template.
    
    Change-Id: Ieb47838a597c5bcab89c1a33d9bc2f2adb57b3b3
    Reviewed-on: https://gerrit.libreoffice.org/79633
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 77acfab36..5355d1050 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -1530,6 +1530,7 @@ private:
 
         _loKitDocument->setView(viewId);
         _loKitDocument->registerCallback(nullptr, nullptr);
+        _loKit->registerCallback(nullptr, nullptr);
 
         int viewCount = _loKitDocument->getViewsCount();
         if (viewCount == 1)
commit d0416781a9e70cdfa7d452022eeb481e95092069
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Mon Sep 23 13:06:52 2019 +0200
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Thu Sep 26 09:46:10 2019 +0200

    tdf#127663: Don't emit 'uno .uno:FontHeight ...' multiple times.
    
    Otherwise it will end up several times on the undo stack, and the user
    has to hit undo several times before undone.
    
    Change-Id: I089c9c9a521e1315b1f85b2866d04ee23a10d3b1
    Reviewed-on: https://gerrit.libreoffice.org/79400
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/loleaflet/js/toolbar.js b/loleaflet/js/toolbar.js
index 10057bb25..afb7b2987 100644
--- a/loleaflet/js/toolbar.js
+++ b/loleaflet/js/toolbar.js
@@ -2073,7 +2073,7 @@ function updateCommandValues(targetName) {
 			data: []
 		});
 
-		$('.fontsizes-select').on('select2:select', onFontSizeSelect);
+		$('.fontsizes-select').off('select2:select', onFontSizeSelect).on('select2:select', onFontSizeSelect);
 		if (fontsSelectValue) {
 			updateFontSizeList(fontsSelectValue);
 		}
commit 0ee9b408cd37c58a769cdd0775e1b1f072e0b6e0
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Wed Sep 25 17:20:24 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Wed Sep 25 16:35:25 2019 +0200

    Set the Presentation of the Document View Controller to fullScreen
    
    Otherwise, on iPadOS 13.1, the document will show up in a view that
    doesn't cover all the screen, which looks weird, and also makes our
    JavaScript code not realize it is on a tablet, so it uses the
    phone-style UI, with toolbar at the bottom, no permanently visible
    menu bar etc.
    
    This also contains some other changes made by Xcode to the storyboard
    file. The only intentional change was changing the Presentation to
    "Full Screen", which added a modalPresentationStyle attribute to the
    viewController element of the Document View Controller scene.
    
    Change-Id: If33b53981ce40948c54b9adfe791b88a24c4e97d
    Reviewed-on: https://gerrit.libreoffice.org/79558
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/ios/Mobile/Base.lproj/Main.storyboard b/ios/Mobile/Base.lproj/Main.storyboard
index 8a253b27a..606a84358 100644
--- a/ios/Mobile/Base.lproj/Main.storyboard
+++ b/ios/Mobile/Base.lproj/Main.storyboard
@@ -1,11 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
-    <device id="ipad9_7" orientation="portrait">
-        <adaptation id="fullscreen"/>
-    </device>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14868" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
+    <device id="ipad9_7" orientation="portrait" layout="fullscreen" appearance="light"/>
     <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -28,7 +25,7 @@
         <!--Document View Controller-->
         <scene sceneID="dkP-xk-x6W">
             <objects>
-                <viewController storyboardIdentifier="DocumentViewController" id="M2k-L8-Olo" customClass="DocumentViewController" sceneMemberID="viewController">
+                <viewController storyboardIdentifier="DocumentViewController" modalPresentationStyle="fullScreen" id="M2k-L8-Olo" customClass="DocumentViewController" sceneMemberID="viewController">
                     <view key="view" contentMode="scaleToFill" id="SIE-Uh-Zny">
                         <rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@@ -63,10 +60,10 @@
                                     <autoresizingMask key="autoresizingMask"/>
                                     <subviews>
                                         <view opaque="NO" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="riJ-1i-vBs">
-                                            <rect key="frame" x="0.0" y="0.0" width="150" height="130"/>
+                                            <rect key="frame" x="0.0" y="0.0" width="200" height="180"/>
                                             <subviews>
                                                 <imageView verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" tag="1" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="79y-w8-uiT">
-                                                    <rect key="frame" x="0.0" y="0.0" width="150" height="130"/>
+                                                    <rect key="frame" x="0.0" y="0.0" width="200" height="180"/>
                                                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                 </imageView>
                                             </subviews>
@@ -79,7 +76,7 @@
                                             </constraints>
                                         </view>
                                         <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" insetsLayoutMarginsFromSafeArea="NO" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fjg-QH-lLg">
-                                            <rect key="frame" x="0.0" y="130" width="150" height="20"/>
+                                            <rect key="frame" x="0.0" y="180" width="200" height="20"/>
                                             <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                             <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                             <nil key="highlightedColor"/>
commit f8ba69bfa0c3621f03eec4bb52a63a5ce39c50d3
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Sep 23 23:13:22 2019 +0200
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Wed Sep 25 10:55:15 2019 +0200

    allow only south east graphic markers for table selection
    
    Change-Id: I581a6a6319c4f3008fb8f5ed14cc57b3df991f42
    Reviewed-on: https://gerrit.libreoffice.org/79427
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 6413d9ffe92ddfb5803f48115a65d973a076ca00)
    Reviewed-on: https://gerrit.libreoffice.org/79435
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/loleaflet/plugins/path-transform/src/Path.Transform.js b/loleaflet/plugins/path-transform/src/Path.Transform.js
index 276537a76..24c9c0448 100644
--- a/loleaflet/plugins/path-transform/src/Path.Transform.js
+++ b/loleaflet/plugins/path-transform/src/Path.Transform.js
@@ -51,6 +51,7 @@ L.Handler.PathTransform = L.Handler.extend({
 	options: {
 		rotation: true,
 		scaling:  true,
+		scaleSouthAndEastOnly:  false,
 		uniformScaling: true,
 		maxZoom:  22,
 
@@ -838,13 +839,19 @@ L.Handler.PathTransform = L.Handler.extend({
 	*/
 	_createHandler: function(latlng, type, index) {
 		var HandleClass = this.options.handleClass;
+		var options = {
+			className: 'leaflet-drag-transform-marker drag-marker--' +
+			index + ' drag-marker--' + type,
+			index:     index,
+			type:      type,
+		};
+		if (this.options.scaleSouthAndEastOnly && index < 5) {
+			options.opacity = 0;
+			options.fill = false;
+			options.interactive = false;
+		}
 		var marker = new HandleClass(latlng,
-			L.Util.extend({}, this.options.handlerOptions, {
-				className: 'leaflet-drag-transform-marker drag-marker--' +
-				index + ' drag-marker--' + type,
-				index:     index,
-				type:      type
-			})
+			L.Util.extend({}, this.options.handlerOptions, options)
 		);
 
 		marker.on('mousedown', this._onScaleStart, this);
diff --git a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
index d02c89b59..7af0d971b 100644
--- a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
+++ b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
@@ -175,6 +175,7 @@ L.TileLayer.include({
 		textMsg = textMsg.substring('tableselected:'.length + 1);
 		var message = JSON.parse(textMsg);
 		this._currentTableData = message;
+		this._hasTableSelection = this._currentTableData.rows != null || this._currentTableData.columns != null;
 		this._updateTableMarkers();
 		this._map.on('zoomend', L.bind(this._onZoom, this));
 	},
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 1fddbdcd6..309edf01f 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -2373,8 +2373,9 @@ L.TileLayer = L.GridLayer.extend({
 				this._graphicMarker.dragging.enable();
 			this._graphicMarker.transform.enable({
 				scaling: extraInfo.isResizable,
-				rotation: extraInfo.isRotatable,
-				uniformScaling: !this._isGraphicAngleDivisibleBy90()});
+				rotation: extraInfo.isRotatable && !this._hasTableSelection,
+				uniformScaling: !this._isGraphicAngleDivisibleBy90(),
+				scaleSouthAndEastOnly: this._hasTableSelection});
 			if (extraInfo.dragInfo && extraInfo.dragInfo.svg) {
 				this._graphicMarker.removeEmbeddedSVG();
 				this._graphicMarker.addEmbeddedSVG(extraInfo.dragInfo.svg);
commit e4dbf12698393f87673c7b1b64478d614583caba
Author:     Marco Cecchetti <mrcekets at gmail.com>
AuthorDate: Mon Jul 1 20:07:54 2019 +0200
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Thu Sep 12 22:25:15 2019 +0200

    loleaflet: pinch + pan issue: move in the opposite direction
    
    When the user pans with 2 fingers the document is moved in the
    opposite direction. So we store the initial center point and invert
    the offset to achieve the correct behavior.
    
    Change-Id: Ief63aa39f56c3b812a90b392ddedc4ba21d813e4

diff --git a/loleaflet/src/map/handler/Map.TouchGesture.js b/loleaflet/src/map/handler/Map.TouchGesture.js
index add6dc008..b9d2a5b39 100644
--- a/loleaflet/src/map/handler/Map.TouchGesture.js
+++ b/loleaflet/src/map/handler/Map.TouchGesture.js
@@ -84,7 +84,8 @@ L.Map.TouchGesture = L.Handler.extend({
 		this._hammer.on('panstart', L.bind(this._onPanStart, this));
 		this._hammer.on('pan', L.bind(this._onPan, this));
 		this._hammer.on('panend', L.bind(this._onPanEnd, this));
-		this._hammer.on('pinchstart pinchmove', L.bind(this._onPinch, this));
+		this._hammer.on('pinchstart', L.bind(this._onPinchStart, this));
+		this._hammer.on('pinchmove', L.bind(this._onPinch, this));
 		this._hammer.on('pinchend', L.bind(this._onPinchEnd, this));
 		this._hammer.on('tripletap', L.bind(this._onTripleTap, this));
 		if (window.ThisIsTheiOSApp)
@@ -99,7 +100,8 @@ L.Map.TouchGesture = L.Handler.extend({
 		this._hammer.off('panstart', L.bind(this._onPanStart, this));
 		this._hammer.off('pan', L.bind(this._onPan, this));
 		this._hammer.off('panend', L.bind(this._onPanEnd, this));
-		this._hammer.off('pinchstart pinchmove', L.bind(this._onPinch, this));
+		this._hammer.off('pinchstart', L.bind(this._onPinchStart, this));
+		this._hammer.off('pinchmove', L.bind(this._onPinch, this));
 		this._hammer.off('pinchend', L.bind(this._onPinchEnd, this));
 		this._hammer.off('doubletap', L.bind(this._onDoubleTap, this));
 		this._hammer.off('tripletap', L.bind(this._onTripleTap, this));
@@ -311,9 +313,21 @@ L.Map.TouchGesture = L.Handler.extend({
 		}
 	},
 
+	_onPinchStart: function (e) {
+		if (this._map.getDocType() !== 'spreadsheet') {
+			this._pinchStartCenter = {x: e.center.x, y: e.center.y};
+		}
+	},
+
 	_onPinch: function (e) {
+		if (!this._pinchStartCenter)
+			return;
+
 		if (this._map.getDocType() !== 'spreadsheet') {
-			this._center = this._map.mouseEventToLatLng({clientX: e.center.x, clientY: e.center.y});
+			// we need to invert the offset or the map is moved in the opposite direction
+			var offset = {x: e.center.x - this._pinchStartCenter.x, y: e.center.y - this._pinchStartCenter.y};
+			var center = {x: this._pinchStartCenter.x - offset.x, y: this._pinchStartCenter.y - offset.y};
+			this._center = this._map.mouseEventToLatLng({clientX: center.x, clientY: center.y});
 			this._zoom = this._map.getScaleZoom(e.scale);
 			this._map._animateZoom(this._center, this._zoom, false, true);
 		}
commit fcd98159807cda91a2135321625fbcc7a93528bb
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Tue Aug 27 23:44:14 2019 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sat Sep 7 22:45:33 2019 +0200

    suppress mouseout even when dragging a graphic selection
    
    This fixes the problem when a mouseout event interrupts dragging
    of a graphic selection. Not sure if it is the most correct thing
    to do, but we can't set "pointer-events" to none on the graphic
    selection as this then wouldn't recognise that we want to move
    it around.
    
    Change-Id: I42a4785fec0b674d47cd4d7c2977877607b03db8
    Reviewed-on: https://gerrit.libreoffice.org/78200
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 1e044a40aa9e0b8e2313d4677755c630cb444448)
    Reviewed-on: https://gerrit.libreoffice.org/78726
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 390e3d628..1fddbdcd6 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -2356,7 +2356,8 @@ L.TileLayer = L.GridLayer.extend({
 				transform: true,
 				stroke: false,
 				fillOpacity: 0,
-				fill: true
+				fill: true,
+				ignoreMouseOut: true
 			});
 
 			if (!this._graphicMarker) {
diff --git a/loleaflet/src/layer/vector/SVGGroup.js b/loleaflet/src/layer/vector/SVGGroup.js
index 7f0f8678a..d4af58cf0 100644
--- a/loleaflet/src/layer/vector/SVGGroup.js
+++ b/loleaflet/src/layer/vector/SVGGroup.js
@@ -11,7 +11,8 @@ L.SVGGroup = L.Layer.extend({
 
 	lastTouchEvent: {
 		clientX: 0,
-		clientY: 0
+		clientY: 0,
+		ignoreMouseOut: false
 	},
 
 	initialize: function (bounds, options) {
@@ -67,7 +68,8 @@ L.SVGGroup = L.Layer.extend({
 
 		L.DomEvent.on(this._dragShape, 'mousemove', this._onDrag, this);
 		L.DomEvent.on(this._dragShape, 'mouseup', this._onDragEnd, this);
-		L.DomEvent.on(this._dragShape, 'mouseout', this._onDragEnd, this);
+		if (!this.options.ignoreMouseOut)
+			L.DomEvent.on(this._dragShape, 'mouseout', this._onDragEnd, this);
 
 		L.DomEvent.on(this._dragShape, 'touchmove', this._onDrag, this);
 		L.DomEvent.on(this._dragShape, 'touchend', this._onDragEnd, this);
@@ -114,7 +116,8 @@ L.SVGGroup = L.Layer.extend({
 			return;
 		L.DomEvent.off(this._dragShape, 'mousemove', this._onDrag, this);
 		L.DomEvent.off(this._dragShape, 'mouseup', this._onDragEnd, this);
-		L.DomEvent.off(this._dragShape, 'mouseout', this._onDragEnd, this);
+		if (!this.options.ignoreMouseOut)
+			L.DomEvent.off(this._dragShape, 'mouseout', this._onDragEnd, this);
 
 		L.DomEvent.off(this._dragShape, 'touchmove', this._onDrag, this);
 		L.DomEvent.off(this._dragShape, 'touchend', this._onDragEnd, this);
commit 43d569526c78679b808720f54eaba932aa5e217e
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Aug 26 20:28:53 2019 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sat Sep 7 22:45:20 2019 +0200

    loleaflet: enable cell selection resize markers for impress table
    
    Change-Id: I77346f13e7955f265653c79a5e4a93c124f0d94e
    Reviewed-on: https://gerrit.libreoffice.org/78126
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit ed8707bcfdaeb9baae057c319f7b3382abcdcd32)
    Reviewed-on: https://gerrit.libreoffice.org/78725

diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 80124d0e3..390e3d628 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -2540,15 +2540,20 @@ L.TileLayer = L.GridLayer.extend({
 				posEnd = this._map.unproject(posEnd);
 				this._cellResizeMarkerEnd.setLatLng(posEnd);
 			}
-			if (!this._cellAutofillMarker.isDragged) {
-				this._map.addLayer(this._cellAutofillMarker);
-				var cellAutoFillMarkerPoisition = cellRectangle.getCenter();
-				cellAutoFillMarkerPoisition.lat = cellRectangle.getSouth();
-				cellAutoFillMarkerPoisition = this._map.project(cellAutoFillMarkerPoisition);
-				var sizeAutoFill = this._cellAutofillMarker._icon.getBoundingClientRect();
-				cellAutoFillMarkerPoisition = cellAutoFillMarkerPoisition.subtract(new L.Point(sizeAutoFill.width / 2, sizeAutoFill.height / 2));
-				cellAutoFillMarkerPoisition = this._map.unproject(cellAutoFillMarkerPoisition);
-				this._cellAutofillMarker.setLatLng(cellAutoFillMarkerPoisition);
+			if (this._cellAutoFillArea) {
+				if (!this._cellAutofillMarker.isDragged) {
+					this._map.addLayer(this._cellAutofillMarker);
+					var cellAutoFillMarkerPoisition = cellRectangle.getCenter();
+					cellAutoFillMarkerPoisition.lat = cellRectangle.getSouth();
+					cellAutoFillMarkerPoisition = this._map.project(cellAutoFillMarkerPoisition);
+					var sizeAutoFill = this._cellAutofillMarker._icon.getBoundingClientRect();
+					cellAutoFillMarkerPoisition = cellAutoFillMarkerPoisition.subtract(new L.Point(sizeAutoFill.width / 2, sizeAutoFill.height / 2));
+					cellAutoFillMarkerPoisition = this._map.unproject(cellAutoFillMarkerPoisition);
+					this._cellAutofillMarker.setLatLng(cellAutoFillMarkerPoisition);
+				}
+				else if (this._cellAutofillMarker) {
+					this._map.removeLayer(this._cellAutofillMarker);
+				}
 			}
 		}
 		else {
@@ -2560,10 +2565,7 @@ L.TileLayer = L.GridLayer.extend({
 
 	// Update text selection handlers.
 	_onUpdateTextSelection: function () {
-		if (this._docType === 'spreadsheet') {
-			this._onUpdateCellResizeMarkers();
-			return;
-		}
+		this._onUpdateCellResizeMarkers();
 
 		var startMarker, endMarker;
 		for (var key in this._selectionHandles) {
commit f5634e5565818f164d1d88ff50dddaacfdc4133d
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Aug 26 17:26:41 2019 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sat Sep 7 22:44:28 2019 +0200

    send table border drag positions as offset, not absolute value
    
    Change-Id: Ie23ff9533eb258acb93a46e00f44141fc7ad12b2
    Reviewed-on: https://gerrit.libreoffice.org/78110
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 45d5715e0d34fefd2c993a812d95b059f1f1963c)
    Reviewed-on: https://gerrit.libreoffice.org/78724
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
index 5f9597a74..d02c89b59 100644
--- a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
+++ b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
@@ -63,6 +63,7 @@ L.TileLayer.include({
 		this._map.addLayer(marker);
 		marker._type = markerType + '-' + entry.type;
 		marker._position = parseInt(entry.position);
+		marker._initialPosition = marker._position;
 		marker._min = parseInt(entry.min);
 		marker._max = parseInt(entry.max);
 		marker._index = parseInt(entry.index);
@@ -260,7 +261,6 @@ L.TileLayer.include({
 			e.target._topBorderPoint.lat = aLatLonPosition.lat;
 			e.target._bottomBorderPoint.lat = aLatLonPosition.lat;
 		}
-
 		e.target._position = newPosition;
 
 		var bounds = new L.LatLngBounds(e.target._topBorderPoint, e.target._bottomBorderPoint);
@@ -276,6 +276,9 @@ L.TileLayer.include({
 			this._map.removeLayer(this._rectangle);
 			this._rectangle = null;
 
+			var offset = newPosition - e.target._initialPosition;
+			e.target._initialPosition =  e.target._position;
+
 			var params = {
 				BorderType: {
 					type : 'string',
@@ -285,9 +288,9 @@ L.TileLayer.include({
 					type : 'uint16',
 					value : e.target._index
 				},
-				NewPosition: {
+				Offset: {
 					type : 'int32',
-					value : e.target._position
+					value : offset
 				}
 			}
 
commit acd847c659e88e7628479f3699857401b3346409
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Fri Sep 6 09:20:57 2019 +0200
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sat Sep 7 22:44:19 2019 +0200

    loleaflet: add column/row selection markers for the table
    
    Change-Id: Iad1037338057e798c3a83695fedb4e6f9ea968f4
    Reviewed-on: https://gerrit.libreoffice.org/78689
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 3ae259238f049e54ae86657d3f4ef731531aab6e)
    Reviewed-on: https://gerrit.libreoffice.org/78723

diff --git a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
index 4ace14da0..5f9597a74 100644
--- a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
+++ b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
@@ -8,15 +8,36 @@ L.TileLayer.include({
 		this._tableColumnMarkers = [];
 		this._tableRowMarkers = [];
 		this._tableMarkersDragged = false;
+		this._tableSelectionColumnMarkers = [];
+		this._tableSelectionRowMarkers = [];
+		this._selectionHeaderDistanceFromTable = 6;
+		this._selectionHeaderHeight = 16;
+	},
+	_convertPixelToTwips: function(pixel) {
+		var point = this._latLngToTwips(this._map.unproject(new L.Point(pixel, 0)));
+		return point.x;
 	},
 	_setMarkerPosition: function(marker) {
-		var point = this._twipsToLatLng(marker._pointTwips, this._map.getZoom());
+		var point = this._twipsToLatLng(marker._positionTwips, this._map.getZoom());
 		point = this._map.project(point);
 		var markerRect = marker._icon.getBoundingClientRect();
-		if (marker._type.startsWith('column'))
+
+		var raiseDelta;
+		var aboveSelectionHeaders = this._selectionHeaderDistanceFromTable + this._selectionHeaderHeight;
+		aboveSelectionHeaders = this._convertPixelToTwips(aboveSelectionHeaders);
+
+		if (marker._type.startsWith('column')) {
 			point = point.subtract(new L.Point(markerRect.width / 2, markerRect.height));
-		else
+			raiseDelta = new L.Point(0, aboveSelectionHeaders);
+		}
+		else {
 			point = point.subtract(new L.Point(markerRect.width, markerRect.height / 2));
+			raiseDelta = new L.Point(aboveSelectionHeaders, 0);
+		}
+
+		raiseDelta = this._map.project(this._twipsToLatLng(raiseDelta, this._map.getZoom()));
+		point = point.subtract(raiseDelta);
+
 		point = this._map.unproject(point);
 		marker.setLatLng(point);
 
@@ -46,29 +67,25 @@ L.TileLayer.include({
 		marker._max = parseInt(entry.max);
 		marker._index = parseInt(entry.index);
 		if (markerType === 'column') {
-			marker._pointTwips = new L.Point(this._tablePositionColumnOffset + marker._position, left);
-			marker._pointTop = new L.Point(this._tablePositionColumnOffset + marker._position, left);
-			marker._pointTop = this._twipsToLatLng(marker._pointTop, this._map.getZoom());
-			marker._pointBottom = new L.Point(this._tablePositionColumnOffset + marker._position, right);
-			marker._pointBottom = this._twipsToLatLng(marker._pointBottom, this._map.getZoom());
+			marker._positionTwips = new L.Point(this._tablePositionColumnOffset + marker._position, left);
+			marker._topBorderPoint = new L.Point(this._tablePositionColumnOffset + marker._position, left);
+			marker._topBorderPoint = this._twipsToLatLng(marker._topBorderPoint, this._map.getZoom());
+			marker._bottomBorderPoint = new L.Point(this._tablePositionColumnOffset + marker._position, right);
+			marker._bottomBorderPoint = this._twipsToLatLng(marker._bottomBorderPoint, this._map.getZoom());
 		}
 		else {
-			marker._pointTwips = new L.Point(left, this._tablePositionRowOffset + marker._position);
-			marker._pointTop = new L.Point(left, this._tablePositionRowOffset + marker._position);
-			marker._pointTop = this._twipsToLatLng(marker._pointTop, this._map.getZoom());
-			marker._pointBottom = new L.Point(right, this._tablePositionRowOffset + marker._position);
-			marker._pointBottom = this._twipsToLatLng(marker._pointBottom, this._map.getZoom());
+			marker._positionTwips = new L.Point(left, this._tablePositionRowOffset + marker._position);
+			marker._topBorderPoint = new L.Point(left, this._tablePositionRowOffset + marker._position);
+			marker._topBorderPoint = this._twipsToLatLng(marker._topBorderPoint, this._map.getZoom());
+			marker._bottomBorderPoint = new L.Point(right, this._tablePositionRowOffset + marker._position);
+			marker._bottomBorderPoint = this._twipsToLatLng(marker._bottomBorderPoint, this._map.getZoom());
 		}
 		this._setMarkerPosition(marker);
-		marker.on('dragstart drag dragend', this._onTableResizeMarkerDrag, this);
+		marker.on('dragstart drag dragend', this._onTableBorderResizeMarkerDrag, this);
 		return marker;
 	},
-	_onTableSelectedMsg: function (textMsg) {
-		if (this._tableMarkersDragged == true) {
-			return;
-		}
-
-		// Clean-up first
+	_updateTableMarkers: function() {
+	// Clean-up first
 		var markerIndex;
 		for (markerIndex = 0; markerIndex < this._tableColumnMarkers.length; markerIndex++) {
 			this._map.removeLayer(this._tableColumnMarkers[markerIndex]);
@@ -80,52 +97,140 @@ L.TileLayer.include({
 		}
 		this._tableRowMarkers = [];
 
-		// Parse the message
-		textMsg = textMsg.substring('tableselected:'.length + 1);
-		var message = JSON.parse(textMsg);
+		for (markerIndex = 0; markerIndex < this._tableSelectionColumnMarkers.length; markerIndex++) {
+			this._map.removeLayer(this._tableSelectionColumnMarkers[markerIndex]);
+		}
+		this._tableSelectionColumnMarkers = [];
+
+		for (markerIndex = 0; markerIndex < this._tableSelectionRowMarkers.length; markerIndex++) {
+			this._map.removeLayer(this._tableSelectionRowMarkers[markerIndex]);
+		}
+		this._tableSelectionRowMarkers = [];
 
 		// Create markers
-		if (message.rows && message.rows.entries.length > 0 && message.columns && message.columns.entries.length > 0) {
-			this._tablePositionColumnOffset = parseInt(message.columns.tableOffset);
-			this._tablePositionRowOffset = parseInt(message.rows.tableOffset);
-			var firstRowPosition = parseInt(message.rows.left) + this._tablePositionRowOffset;
-			var lastRowPosition = parseInt(message.rows.right) + this._tablePositionRowOffset;
-			var firstColumnPosition = parseInt(message.columns.left) + this._tablePositionColumnOffset;
-			var lastColumnPosition = parseInt(message.columns.right) + this._tablePositionColumnOffset;
+		if (this._currentTableData.rows && this._currentTableData.rows.entries.length > 0 && this._currentTableData.columns && this._currentTableData.columns.entries.length > 0) {
+			this._tablePositionColumnOffset = parseInt(this._currentTableData.columns.tableOffset);
+			this._tablePositionRowOffset = parseInt(this._currentTableData.rows.tableOffset);
+			var firstRowPosition = parseInt(this._currentTableData.rows.left) + this._tablePositionRowOffset;
+			var lastRowPosition = parseInt(this._currentTableData.rows.right) + this._tablePositionRowOffset;
+			var firstColumnPosition = parseInt(this._currentTableData.columns.left) + this._tablePositionColumnOffset;
+			var lastColumnPosition = parseInt(this._currentTableData.columns.right) + this._tablePositionColumnOffset;
 			var markerX, i, entry;
 
-			entry = { type: 'left', position: message.columns.left, index: 0 };
-			markerX = this._createMarker('column', entry, firstRowPosition, lastRowPosition);
-			this._tableColumnMarkers.push(markerX);
+			var columnPositions = [];
+			var rowPositions = [];
+
+			columnPositions.push(parseInt(this._currentTableData.columns.left));
+			if (this._map.getDocType() !== 'presentation') {
+				entry = { type: 'left', position: this._currentTableData.columns.left, index: 0 };
+				markerX = this._createMarker('column', entry, firstRowPosition, lastRowPosition);
+				this._tableColumnMarkers.push(markerX);
+			}
 
-			for (i = 0; i < message.columns.entries.length; i++) {
-				entry = message.columns.entries[i];
+			for (i = 0; i < this._currentTableData.columns.entries.length; i++) {
+				entry = this._currentTableData.columns.entries[i];
+				columnPositions.push(parseInt(entry.position));
 				entry.type = 'middle';
 				entry.index = i;
 				markerX = this._createMarker('column', entry, firstRowPosition, lastRowPosition);
 				this._tableColumnMarkers.push(markerX);
 			}
 
-			entry = { type: 'right', position: message.columns.right, index: 0 };
+			columnPositions.push(parseInt(this._currentTableData.columns.right));
+
+			entry = { type: 'right', position: this._currentTableData.columns.right, index: 0 };
 			markerX = this._createMarker('column', entry, firstRowPosition, lastRowPosition);
 			this._tableColumnMarkers.push(markerX);
 
-			for (i = 0; i < message.rows.entries.length; i++) {
-				entry = message.rows.entries[i];
+			this._addSelectionMarkers('column', columnPositions, firstRowPosition, lastRowPosition);
+
+			rowPositions.push(parseInt(this._currentTableData.rows.left));
+
+			for (i = 0; i < this._currentTableData.rows.entries.length; i++) {
+				entry = this._currentTableData.rows.entries[i];
+				rowPositions.push(parseInt(entry.position));
 				entry.type = 'middle';
 				entry.index = i;
 				markerX = this._createMarker('row', entry, firstColumnPosition, lastColumnPosition);
 				this._tableRowMarkers.push(markerX);
 			}
 
-			entry = { type: 'right', position: message.rows.right };
+			rowPositions.push(parseInt(this._currentTableData.rows.right));
+			entry = { type: 'right', position: this._currentTableData.rows.right };
 			markerX = this._createMarker('row', entry, firstColumnPosition, lastColumnPosition);
 			this._tableRowMarkers.push(markerX);
+
+			this._addSelectionMarkers('row', rowPositions, firstColumnPosition, lastColumnPosition);
+		}
+	},
+	_onZoom: function () {
+		this._updateTableMarkers();
+	},
+	_onTableSelectedMsg: function (textMsg) {
+		if (this._tableMarkersDragged == true) {
+			return;
+		}
+		// Parse the message
+		textMsg = textMsg.substring('tableselected:'.length + 1);
+		var message = JSON.parse(textMsg);
+		this._currentTableData = message;
+		this._updateTableMarkers();
+		this._map.on('zoomend', L.bind(this._onZoom, this));
+	},
+	_addSelectionMarkers: function (type, positions, start, end) {
+		if (positions.length < 2)
+			return;
+
+		var startX, endX, startY, endY;
+		var point1, point2;
+
+		var delta1 = this._convertPixelToTwips(this._selectionHeaderDistanceFromTable);
+		var delta2 = this._convertPixelToTwips(this._selectionHeaderDistanceFromTable + this._selectionHeaderHeight);
+
+		for (var i = 0; i < positions.length - 1; i++) {
+			if (type === 'column') {
+				startX = this._tablePositionColumnOffset + positions[i];
+				endX = this._tablePositionColumnOffset + positions[i + 1];
+				startY = start;
+				endY = end;
+				point1 = this._twipsToLatLng(new L.Point(startX, startY  - delta1), this._map.getZoom());
+				point2 = this._twipsToLatLng(new L.Point(endX, startY  - delta2), this._map.getZoom());
+			}
+			else {
+				startX = start;
+				endX = end;
+				startY = this._tablePositionRowOffset + positions[i];
+				endY = this._tablePositionRowOffset + positions[i + 1];
+				point1 = this._twipsToLatLng(new L.Point(startX - delta1, startY), this._map.getZoom());
+				point2 = this._twipsToLatLng(new L.Point(startX - delta2, endY), this._map.getZoom());
+			}
+
+			var bounds = new L.LatLngBounds(point1, point2);
+			var selectionRectangle = new L.Rectangle(bounds, {
+				stroke: true, weight: 1, color: '#777777',
+				fillOpacity: 1, fillColor: '#dddddd'
+			});
+
+			selectionRectangle._start = { x: startX, y: startY };
+			selectionRectangle._end = { x: endX, y: endY };
+
+			if (type === 'column')
+				this._tableSelectionColumnMarkers.push(selectionRectangle);
+			else
+				this._tableSelectionRowMarkers.push(selectionRectangle);
+
+			selectionRectangle.on('click', this._onSelectRowColumnClick, this);
+			this._map.addLayer(selectionRectangle);
 		}
 	},
+	_onSelectRowColumnClick: function(e) {
+		// fake seelcting a column
+		this._postSelectTextEvent('start', e.target._start.x + 5, e.target._start.y + 5);
+		this._postSelectTextEvent('end', e.target._end.x - 5, e.target._end.y - 5);
+	},
 
 	// Update dragged text selection.
-	_onTableResizeMarkerDrag: function (e) {
+	_onTableBorderResizeMarkerDrag: function (e) {
 		if (e.type === 'dragstart') {
 			e.target.isDragged = true;
 			this._tableMarkersDragged = true;
@@ -147,18 +252,18 @@ L.TileLayer.include({
 		var newPosition;
 		if (e.target._type.startsWith('column')) {
 			newPosition = aMousePosition.x - this._tablePositionColumnOffset;
-			e.target._pointTop.lng = aLatLonPosition.lng;
-			e.target._pointBottom.lng = aLatLonPosition.lng;
+			e.target._topBorderPoint.lng = aLatLonPosition.lng;
+			e.target._bottomBorderPoint.lng = aLatLonPosition.lng;
 		}
 		else {
 			newPosition = aMousePosition.y - this._tablePositionRowOffset;
-			e.target._pointTop.lat = aLatLonPosition.lat;
-			e.target._pointBottom.lat = aLatLonPosition.lat;
+			e.target._topBorderPoint.lat = aLatLonPosition.lat;
+			e.target._bottomBorderPoint.lat = aLatLonPosition.lat;
 		}
 
 		e.target._position = newPosition;
 
-		var bounds = new L.LatLngBounds(e.target._pointTop, e.target._pointBottom);
+		var bounds = new L.LatLngBounds(e.target._topBorderPoint, e.target._bottomBorderPoint);
 
 		if (e.type === 'dragstart') {
 			this._rectangle = new L.Rectangle(bounds);
commit 64c4e845c73d2e258fde5dc117244178207d67a6
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sat Sep 7 19:13:07 2019 +0200
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sat Sep 7 19:15:50 2019 +0200

    fix HTTPWSTest::testInactiveClient test failure
    
    Change-Id: Ic76e43937a9bea00eec950a54ddd50f747dc707e
    Reviewed-on: https://gerrit.libreoffice.org/78752
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/test/httpwstest.cpp b/test/httpwstest.cpp
index a44480b98..8e2beaae5 100644
--- a/test/httpwstest.cpp
+++ b/test/httpwstest.cpp
@@ -1386,7 +1386,8 @@ void HTTPWSTest::testInactiveClient()
                                             token == "viewcursorvisible:" ||
                                             token == "viewinfo:" ||
                                             token == "editor:" ||
-                                            token == "context:");
+                                            token == "context:" ||
+                                            token == "tableselected:");
 
                     // End when we get state changed.
                     return (token != "statechanged:");
commit 102bd72c3a74e581ff8506d8feda39878d7005c6
Author:     kaishu-sahu <kaishusahu101 at gmail.com>
AuthorDate: Sun Jul 28 05:13:26 2019 +0530
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Sep 6 12:04:27 2019 +0200

    android: add support for screen dimming from JS.
    
    Change-Id: Icd766c7dcc9c2d62ec90945ec88fa46f88a4711d
    Reviewed-on: https://gerrit.libreoffice.org/76489
    Reviewed-by: Jan Holesovsky <kendy at collabora.com>
    Tested-by: Jan Holesovsky <kendy at collabora.com>
    (cherry picked from commit 0f9492268e8684b16e9c3d92be26eeb814fcf7a3)
    Reviewed-on: https://gerrit.libreoffice.org/78697

diff --git a/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java b/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java
index 2258a78a2..95c7c040f 100644
--- a/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java
+++ b/android/lib/src/main/java/org/libreoffice/androidlib/LOActivity.java
@@ -32,6 +32,7 @@ import android.print.PrintAttributes;
 import android.print.PrintDocumentAdapter;
 import android.print.PrintManager;
 import android.util.Log;
+import android.view.WindowManager;
 import android.webkit.JavascriptInterface;
 import android.webkit.ValueCallback;
 import android.webkit.WebChromeClient;
@@ -154,9 +155,10 @@ public class LOActivity extends AppCompatActivity {
         }
     }
 
-    /** Copies fonts except the NotoSans from the system to our location.
-     *  This is necessary because the NotoSans is huge and fontconfig needs
-     *  ages to parse them.
+    /**
+     * Copies fonts except the NotoSans from the system to our location.
+     * This is necessary because the NotoSans is huge and fontconfig needs
+     * ages to parse them.
      */
     private static boolean copyFonts(String fromPath, String targetDir) {
         try {
@@ -171,8 +173,7 @@ public class LOActivity extends AppCompatActivity {
                 if (!fontFileName.equals("Roboto-Regular.ttf")) {
                     Log.i(TAG, "Ignored font file: " + fontFile);
                     continue;
-                }
-                else {
+                } else {
                     Log.i(TAG, "Copying font file: " + fontFile);
                 }
 
@@ -214,6 +215,7 @@ public class LOActivity extends AppCompatActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
         sPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
         updatePreferences();
 
@@ -579,6 +581,24 @@ public class LOActivity extends AppCompatActivity {
                 });
                 break;
             }
+            case "DIM_SCREEN": {
+                mainHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                    }
+                });
+                return false;
+            }
+            case "LIGHT_SCREEN": {
+                mainHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                    }
+                });
+                return false;
+            }
         }
         return true;
     }
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index e46e7597d..69d7afef0 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -1128,6 +1128,11 @@ L.Map = L.Evented.extend({
 		this._active = false;
 		clearTimeout(vex.timer);
 
+		if (window.ThisIsTheAndroidApp) {
+			window.postMobileMessage('DIM_SCREEN');
+			return;
+		}
+
 		var message = '';
 		var map = this;
 		if (!map['wopi'].DisableInactiveMessages) {
@@ -1173,6 +1178,9 @@ L.Map = L.Evented.extend({
 
 	notifyActive : function() {
 		this.lastActiveTime = Date.now();
+		if (window.ThisIsTheAndroidApp) {
+			window.postMobileMessage('LIGHT_SCREEN');
+		}
 	},
 
 	_dimIfInactive: function () {
commit 485a68d9579a69595d7d8ba2f3fed5c686ff4527
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Mon Aug 26 16:23:04 2019 -0400
Commit:     Mert Tumer <mert.tumer at collabora.com>
CommitDate: Mon Sep 2 02:49:30 2019 +0300

    Add watermark opacity setting.
    
    Change-Id: I839e8aef91acfed40d4afd8c1b50176ed54c670a

diff --git a/common/Session.cpp b/common/Session.cpp
index a8405d4e9..e5a70c081 100644
--- a/common/Session.cpp
+++ b/common/Session.cpp
@@ -55,7 +55,8 @@ Session::Session(const std::string& name, const std::string& id, bool readOnly)
     _isReadOnly(readOnly),
     _docPassword(""),
     _haveDocPassword(false),
-    _isDocPasswordProtected(false)
+    _isDocPasswordProtected(false),
+    _watermarkOpacity(0.2)
 {
 }
 
@@ -156,6 +157,11 @@ void Session::parseDocOptions(const std::vector<std::string>& tokens, int& part,
             Poco::URI::decode(value, _watermarkText);
             ++offset;
         }
+        else if (name == "watermarkOpacity")
+        {
+            _watermarkOpacity = std::stod(value);
+            ++offset;
+        }
         else if (name == "timestamp")
         {
             timestamp = value;
diff --git a/common/Session.hpp b/common/Session.hpp
index ddee50d55..6955b1e66 100644
--- a/common/Session.hpp
+++ b/common/Session.hpp
@@ -102,8 +102,12 @@ public:
 
     const std::string& getDocOptions() const { return _docOptions; }
 
+    bool hasWatermark() const { return !_watermarkText.empty() && _watermarkOpacity > 0.0; }
+
     const std::string& getWatermarkText() const { return _watermarkText; }
 
+    double getWatermarkOpacity() const { return _watermarkOpacity; }
+
     const std::string& getLang() const { return _lang; }
 
     bool getHaveDocPassword() const { return _haveDocPassword; }
@@ -203,6 +207,9 @@ private:
     /// In case a watermark has to be rendered on each tile.
     std::string _watermarkText;
 
+    /// Opacity in case a watermark has to be rendered on each tile.
+    double _watermarkOpacity;
+
     /// Language for the document based on what the user has in the UI.
     std::string _lang;
 };
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 9c8d858b8..77acfab36 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -588,13 +588,14 @@ public:
 class Watermark
 {
 public:
-    Watermark(const std::shared_ptr<lok::Document>& loKitDoc, const std::string& text)
+    Watermark(const std::shared_ptr<lok::Document>& loKitDoc, const std::string& text,
+    const std::shared_ptr<ChildSession> & session)
         : _loKitDoc(loKitDoc)
         , _text(text)
         , _font("Liberation Sans")
         , _width(0)
         , _height(0)
-        , _alphaLevel(0.2)
+        , _alphaLevel(session->getWatermarkOpacity())
     {
     }
 
@@ -1815,7 +1816,7 @@ private:
             _renderOpts = renderOpts;
 
             if (!watermarkText.empty())
-                _docWatermark.reset(new Watermark(_loKitDocument, watermarkText));
+                _docWatermark.reset(new Watermark(_loKitDocument, watermarkText, session));
         }
         else
         {
diff --git a/loolwsd.xml.in b/loolwsd.xml.in
index 8475a23d3..8ae1c9bdd 100644
--- a/loolwsd.xml.in
+++ b/loolwsd.xml.in
@@ -107,6 +107,10 @@
       <capabilities desc="Should we require capabilities to isolate processes into chroot jails" type="bool" default="true">true</capabilities>
     </security>
 
+    <watermark>
+      <opacity desc="Opacity of on-screen watermark from 0.0 to 1.0" type="double" default="0.2"></opacity>
+    </watermark>
+
     <storage desc="Backend storage">
         <filesystem allow="false" />
         <wopi desc="Allow/deny wopi storage. Mutually exclusive with webdav." allow="true">
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index 564a664a5..36c0c5965 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -518,6 +518,7 @@ bool ClientSession::loadDocument(const char* /*buffer*/, int /*length*/,
             std::string encodedWatermarkText;
             Poco::URI::encode(getWatermarkText(), "", encodedWatermarkText);
             oss << " watermarkText=" << encodedWatermarkText;
+            oss << " watermarkOpacity=" << LOOLWSD::getConfigValue<double>("watermark.opacity", 0.2);
         }
 
         if (!getDocOptions().empty())
commit 7efb19ab4abd72ace6261ae6f73a81b22be0db1c
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Thu Aug 29 18:21:01 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Thu Aug 29 17:43:02 2019 +0200

    Revert "Make the image resize and rotate handles larger in a mobile app"
    
    There is now other code that takes care of it.
    
    This reverts commit 3cc714b49b6e29429d45818a281cd77a209dbec2.
    
    Change-Id: I9c777e1592d1c5e0fc931307b24e63743cd4da5b
    Reviewed-on: https://gerrit.libreoffice.org/78279
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/plugins/path-transform/src/Path.Transform.js b/loleaflet/plugins/path-transform/src/Path.Transform.js
index 1e4b1cd0c..276537a76 100644
--- a/loleaflet/plugins/path-transform/src/Path.Transform.js
+++ b/loleaflet/plugins/path-transform/src/Path.Transform.js
@@ -552,7 +552,7 @@ L.Handler.PathTransform = L.Handler.extend({
 		L.PathTransform.pointOnLine(
 			map.latLngToLayerPoint(bottom),
 			map.latLngToLayerPoint(topPoint),
-		        (window.ThisIsAMobileApp ? this.options.handleLength * 3 : this.options.handleLength))
+			this.options.handleLength)
 		);
 
 		this._handleLine = new L.Polyline([topPoint, handlerPosition],
diff --git a/loleaflet/src/layer/vector/CircleMarker.js b/loleaflet/src/layer/vector/CircleMarker.js
index fd9a2e1fa..837471440 100644
--- a/loleaflet/src/layer/vector/CircleMarker.js
+++ b/loleaflet/src/layer/vector/CircleMarker.js
@@ -14,8 +14,6 @@ L.CircleMarker = L.Path.extend({
 		L.setOptions(this, options);
 		this._latlng = L.latLng(latlng);
 		this._radius = this.options.radius;
-		if (window.ThisIsAMobileApp)
-			this._radius *= 3;
 	},
 
 	setLatLng: function (latlng) {
@@ -30,8 +28,6 @@ L.CircleMarker = L.Path.extend({
 
 	setRadius: function (radius) {
 		this.options.radius = this._radius = radius;
-		if (window.ThisIsAMobileApp)
-			this._radius *= 3;
 		return this.redraw();
 	},
 
commit aa56728d44aa372d62ff145950707ed7680bf82d
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Fri Jun 28 11:50:37 2019 -0400
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Thu Aug 29 17:16:07 2019 +0200

    loleaflet: mobile: enable the option to scale and rotate graphics
    
    (This side-port fixes tdf#126963 in this branch.)
    
    Change-Id: I66e082ae7bf7551de90002164a87d2a267ea1523
    Reviewed-on: https://gerrit.libreoffice.org/78275
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/src/map/handler/Map.TouchGesture.js b/loleaflet/src/map/handler/Map.TouchGesture.js
index 87d206f6d..add6dc008 100644
--- a/loleaflet/src/map/handler/Map.TouchGesture.js
+++ b/loleaflet/src/map/handler/Map.TouchGesture.js
@@ -12,7 +12,8 @@ L.Map.TouchGesture = L.Handler.extend({
 	statics: {
 		MAP: 1,
 		CURSOR: 2,
-		GRAPHIC: 4
+		GRAPHIC: 4,
+		MARKER: 8
 	},
 
 	initialize: function (map) {
@@ -123,7 +124,13 @@ L.Map.TouchGesture = L.Handler.extend({
 			    layerPoint = this._map.containerPointToLayerPoint(containerPoint),
 			    latlng = this._map.layerPointToLatLng(layerPoint);
 
-			if (this._map._docLayer._graphicMarker && this._map._docLayer._graphicMarker.getBounds().contains(latlng)) {
+			if (this._map._docLayer._graphicMarker) {
+				this._marker = this._map._docLayer._graphicMarker.transform.getMarker(layerPoint);
+			}
+
+			if (this._marker) {
+				this._state = L.Map.TouchGesture.MARKER;
+			} else if (this._map._docLayer._graphicMarker && this._map._docLayer._graphicMarker.getBounds().contains(latlng)) {
 				this._state = L.Map.TouchGesture.GRAPHIC;
 			} else if (this._map._docLayer._cellCursor && this._map._docLayer._cellCursor.contains(latlng)) {
 				this._state = L.Map.TouchGesture.CURSOR;
@@ -134,6 +141,7 @@ L.Map.TouchGesture = L.Handler.extend({
 
 		if (e.isLast && this._state !== L.Map.TouchGesture.MAP) {
 			this._state = L.Map.TouchGesture.hitTest.MAP;
+			this._marker = undefined;
 		}
 
 		if ($(e.srcEvent.target).has(this._map._mapPane)) {
@@ -256,7 +264,9 @@ L.Map.TouchGesture = L.Handler.extend({
 			}
 		}
 
-		if (this._state === L.Map.TouchGesture.GRAPHIC) {
+		if (this._state === L.Map.TouchGesture.MARKER) {
+			this._map._fireDOMEvent(this._marker, e.srcEvent, 'mousedown');
+		} else if (this._state === L.Map.TouchGesture.GRAPHIC) {
 			this._map._docLayer._graphicMarker._onDragStart(e.srcEvent);
 		} else if (this._state === L.Map.TouchGesture.CURSOR) {
 			this._map._docLayer._postMouseEvent('buttondown', mousePos.x, mousePos.y, 1, 1, 0);
@@ -272,7 +282,9 @@ L.Map.TouchGesture = L.Handler.extend({
 		    latlng = this._map.layerPointToLatLng(layerPoint),
 		    mousePos = this._map._docLayer._latLngToTwips(latlng);
 
-		if (this._state === L.Map.TouchGesture.GRAPHIC) {
+		if (this._state === L.Map.TouchGesture.MARKER) {
+			this._map._fireDOMEvent(this._map, e.srcEvent, 'mousemove');
+		} else if (this._state === L.Map.TouchGesture.GRAPHIC) {
 			this._map._docLayer._graphicMarker._onDrag(e.srcEvent);
 		} else if (this._state === L.Map.TouchGesture.CURSOR) {
 			this._map._docLayer._postMouseEvent('move', mousePos.x, mousePos.y, 1, 1, 0);
@@ -288,7 +300,9 @@ L.Map.TouchGesture = L.Handler.extend({
 		    latlng = this._map.layerPointToLatLng(layerPoint),
 		    mousePos = this._map._docLayer._latLngToTwips(latlng);
 
-		if (this._state === L.Map.TouchGesture.GRAPHIC) {
+		if (this._state === L.Map.TouchGesture.MARKER) {
+			this._map._fireDOMEvent(this._map, e.srcEvent, 'mouseup');
+		} else if (this._state === L.Map.TouchGesture.GRAPHIC) {
 			this._map._docLayer._graphicMarker._onDragEnd(e.srcEvent);
 		} else if (this._state === L.Map.TouchGesture.CURSOR) {
 			this._map._docLayer._postMouseEvent('buttonup', mousePos.x, mousePos.y, 1, 1, 0);
commit c0d1466f8e7a5f5308b0704d1ef956f8cf8e866f
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Fri Jun 28 11:49:50 2019 -0400
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Thu Aug 29 16:57:42 2019 +0200

    loleaflet: mobile: prepare manual dragging for scale and rotate of graphics
    
    (Side-port that is part of fix for tdf#126963 in this branch.)
    
    Change-Id: Ib0eae5a9e96a5305fcddbb6f508fc23a5db846a5
    Reviewed-on: https://gerrit.libreoffice.org/78274
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/plugins/path-transform/src/Path.Transform.js b/loleaflet/plugins/path-transform/src/Path.Transform.js
index cc51426a5..1e4b1cd0c 100644
--- a/loleaflet/plugins/path-transform/src/Path.Transform.js
+++ b/loleaflet/plugins/path-transform/src/Path.Transform.js
@@ -56,7 +56,7 @@ L.Handler.PathTransform = L.Handler.extend({
 
 		// edge handlers
 		handlerOptions: {
-			radius:      5,
+			radius:      L.Browser.touch && !L.Browser.pointer ? 10 : 5,
 			fillColor:   '#ffffff',
 			color:       '#202020',
 			fillOpacity: 1,
@@ -81,7 +81,7 @@ L.Handler.PathTransform = L.Handler.extend({
 			setCursor: true
 		},
 		// rotation handle length
-		handleLength: 20,
+		handleLength: L.Browser.touch && !L.Browser.pointer ? 40 : 20,
 
 		// maybe I'll add skewing in the future
 		edgesCount:   4,
@@ -238,6 +238,18 @@ L.Handler.PathTransform = L.Handler.extend({
 		return this;
 	},
 
+	/**
+	* @param  {L.Point}   point
+	*/
+	getMarker: function(point) {
+		for (var i = 0, len = this._handlers.length; i < len; i++) {
+			var handler = this._handlers[i];
+			if (handler._containsPoint(point)) {
+				return handler;
+			}
+		}
+		return undefined;
+	},
 
 	/**
 	* Update the polygon and handlers preview, no reprojection
@@ -611,6 +623,9 @@ L.Handler.PathTransform = L.Handler.extend({
 	* @param  {Event} evt
 	*/
 	_onRotate: function(evt) {
+		if (!this._rect || !this._rotationStart) {
+			return;
+		}
 		var pos = evt.layerPoint;
 		var previous = this._rotationStart;
 		var origin   = this._rotationOriginPt;
@@ -635,6 +650,9 @@ L.Handler.PathTransform = L.Handler.extend({
 	* @param  {Event} evt
 	*/
 	_onRotateEnd: function(evt) {
+		if (!this._rect || !this._rotationStart) {
+			return;
+		}
 		var pos = evt.layerPoint;
 		var previous = this._rotationStart;
 		var origin = this._rotationOriginPt;
@@ -652,6 +670,8 @@ L.Handler.PathTransform = L.Handler.extend({
 
 		this._apply();
 		this._path.fire('rotateend', { layer: this._path, rotation: angle });
+
+		this._rotationStart = undefined;
 	},
 
 
@@ -706,6 +726,10 @@ L.Handler.PathTransform = L.Handler.extend({
 	* @param  {Event} evt
 	*/
 	_onScale: function(evt) {
+		if (!this._rect || !this._scaleOrigin) {
+			return;
+		}
+
 		var originPoint = this._originMarker._point;
 		var ratioX, ratioY;
 
@@ -740,6 +764,9 @@ L.Handler.PathTransform = L.Handler.extend({
 	* @param  {Event} evt
 	*/
 	_onScaleEnd: function(/*evt*/) {
+		if (!this._rect || !this._scaleOrigin) {
+			return;
+		}
 		this._activeMarker.removeEventParent(this._map);
 		this._map
 			.off('mousemove', this._onScale,    this)
@@ -768,6 +795,8 @@ L.Handler.PathTransform = L.Handler.extend({
 			scale: this._scale.clone(),
 			pos: this._getPoints()[index]
 		});
+
+		this._scaleOrigin = undefined;
 	},
 
 
@@ -879,13 +908,6 @@ L.Handler.PathTransform = L.Handler.extend({
 	}
 });
 
-
-L.Path.addInitHook(function() {
-	if (this.options.transform) {
-		this.transform = new L.Handler.PathTransform(this, this.options.transform);
-	}
-});
-
 L.SVGGroup.addInitHook(function() {
 	if (this.options.transform) {
 		this.transform = new L.Handler.PathTransform(this, this.options.transform);
commit 48ac27e694167fd24dbc50b686849c1067bd2107
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Mon Aug 26 16:25:42 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Mon Aug 26 15:42:26 2019 +0200

    There should not be a "filter" directory directly at the top level
    
    Change-Id: Icfc86d57924f655d5d3f3f1245aa011012d898f1
    Reviewed-on: https://gerrit.libreoffice.org/78143
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/ios/Mobile.xcodeproj/project.pbxproj b/ios/Mobile.xcodeproj/project.pbxproj
index 903d4dfdc..530bedf9b 100644
--- a/ios/Mobile.xcodeproj/project.pbxproj
+++ b/ios/Mobile.xcodeproj/project.pbxproj
@@ -44,7 +44,6 @@
 		BE8D773A2136762600AC58EA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BE8D77392136762600AC58EA /* Assets.xcassets */; };
 		BE8D773D2136762600AC58EA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE8D773B2136762600AC58EA /* LaunchScreen.storyboard */; };
 		BE8D77402136762600AC58EA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BE8D773F2136762600AC58EA /* main.m */; };
-		BE8D85C9214055F3009F1860 /* filter in Resources */ = {isa = PBXBuildFile; fileRef = BE8D85BB214055F2009F1860 /* filter */; };
 		BE8D85CA214055F3009F1860 /* offapi.rdb in Resources */ = {isa = PBXBuildFile; fileRef = BE8D85BC214055F2009F1860 /* offapi.rdb */; };
 		BE8D85CB214055F3009F1860 /* share in Resources */ = {isa = PBXBuildFile; fileRef = BE8D85BD214055F2009F1860 /* share */; };
 		BE8D85CC214055F3009F1860 /* config in Resources */ = {isa = PBXBuildFile; fileRef = BE8D85BE214055F2009F1860 /* config */; };
@@ -879,7 +878,6 @@
 		BE8D773C2136762600AC58EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		BE8D773E2136762600AC58EA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		BE8D773F2136762600AC58EA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
-		BE8D85BB214055F2009F1860 /* filter */ = {isa = PBXFileReference; lastKnownFileType = folder; name = filter; path = "../../../lobuilddir-symlink/workdir/CustomTarget/ios/resources/filter"; sourceTree = "<group>"; };
 		BE8D85BC214055F2009F1860 /* offapi.rdb */ = {isa = PBXFileReference; lastKnownFileType = file; name = offapi.rdb; path = "../../../lobuilddir-symlink/workdir/CustomTarget/ios/resources/offapi.rdb"; sourceTree = "<group>"; };
 		BE8D85BD214055F2009F1860 /* share */ = {isa = PBXFileReference; lastKnownFileType = folder; name = share; path = "../../../lobuilddir-symlink/workdir/CustomTarget/ios/resources/share"; sourceTree = "<group>"; };
 		BE8D85BE214055F2009F1860 /* config */ = {isa = PBXFileReference; lastKnownFileType = folder; name = config; path = "../../../lobuilddir-symlink/workdir/CustomTarget/ios/resources/config"; sourceTree = "<group>"; };
@@ -1157,7 +1155,6 @@
 				BE80E46721B7066C00859C97 /* Templates */,
 				BE80E43121AD92F600859C97 /* Fonts */,
 				BE8D85BE214055F2009F1860 /* config */,
-				BE8D85BB214055F2009F1860 /* filter */,
 				BE8D85C6214055F3009F1860 /* fundamentalrc */,
 				BE8D85BC214055F2009F1860 /* offapi.rdb */,
 				BE8D85C0214055F2009F1860 /* oovbaapi.rdb */,
commit 7e1a69671c15bd09759c3babfb9588436bcb4142
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Fri Aug 23 13:03:51 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Fri Aug 23 12:21:44 2019 +0200

    Guard against uncaught "null is not an object" exception
    
    Change-Id: I3b6d25185a3919ef5d15ce1b9e0604ca697c43fe
    Reviewed-on: https://gerrit.libreoffice.org/78006
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/plugins/path-transform/src/Path.Drag.js b/loleaflet/plugins/path-transform/src/Path.Drag.js
index 63e0fd180..80a41d900 100644
--- a/loleaflet/plugins/path-transform/src/Path.Drag.js
+++ b/loleaflet/plugins/path-transform/src/Path.Drag.js
@@ -158,6 +158,9 @@ L.Handler.PathDrag = L.Handler.extend(/** @lends  L.Path.Drag.prototype */ {
 			}
 		}
 
+		if (this._startPoint === null)
+			return;
+
 		var x = containerPoint.x;
 		var y = containerPoint.y;
 
commit d07bcd77c5bac2d9514e269deead9e33f174210f
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Thu Aug 22 16:41:26 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Thu Aug 22 16:41:26 2019 +0300

    Add "Save as PDF" also for presentations and spreadsheets in the iOS app
    
    Change-Id: Icc9f2f31972f7fcd276e1d08c3834a7b87006dc5

diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index f13955200..7efdfe27b 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -252,6 +252,7 @@ L.Control.Menubar = L.Control.extend({
 					{name: _('ODF presentation (.odp)'), id: 'downloadas-odp', type: 'action'},
 					{name: _('PowerPoint 2003 Presentation (.ppt)'), id: 'downloadas-ppt', type: 'action'},
 					{name: _('PowerPoint Presentation (.pptx)'), id: 'downloadas-pptx', type: 'action'}]},
+				{name: _('Save as PDF'), id: 'downloadas-pdf', mobileapp: true, type: 'action'},
 				{type: 'separator'},
 				{name: _('Close document'), id: 'closedocument', type: 'action'}
 			]},
@@ -340,6 +341,7 @@ L.Control.Menubar = L.Control.extend({
 					{name: _('ODF spreadsheet (.ods)'), id: 'downloadas-ods', type: 'action'},
 					{name: _('Excel 2003 Spreadsheet (.xls)'), id: 'downloadas-xls', type: 'action'},
 					{name: _('Excel Spreadsheet (.xlsx)'), id: 'downloadas-xlsx', type: 'action'}]},
+				{name: _('Save as PDF'), id: 'downloadas-pdf', mobileapp: true, type: 'action'},
 				{type: 'separator'},
 				{name: _('Close document'), id: 'closedocument', type: 'action'}
 			]},
commit 9b5b91669aa236bfa04b4b7c1594325c9e6f3016
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Thu Aug 22 15:47:12 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Thu Aug 22 15:12:44 2019 +0200

    tdf#126968: Implement "Save as PDF" in the iOS app
    
    For now, add an entry "Save as PDF" to the File menu in the iOS app.
    Handle in an iOS-specific way in ChildSession::downloadAs(). The PDF
    is saved in the app's document directory on the device. The name of
    the PDF is the basename of the document being edited with the "pdf"
    extension.
    
    Change-Id: Ib0059a86b03b978996eb4cadf230ba7f0abcba62
    Reviewed-on: https://gerrit.libreoffice.org/77958
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index 2f66b67fd..40a06c0e4 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -862,6 +862,15 @@ bool ChildSession::downloadAs(const char* /*buffer*/, int /*length*/, const std:
         filterOptions += std::string(",Watermark=") + getWatermarkText() + std::string("WATERMARKEND");
     }
 
+#ifdef IOS
+    NSArray<NSString *> *pathComponents = [[NSURL URLWithString:[NSString stringWithUTF8String:getDocURL().c_str()]] pathComponents];
+    NSString *baseName = [[pathComponents lastObject] stringByDeletingPathExtension];
+    NSURL *documentDirectory = [NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0];
+    NSURL *pdfURL = [documentDirectory URLByAppendingPathComponent:[baseName stringByAppendingString:@".pdf"]];
+    getLOKitDocument()->saveAs([[pdfURL absoluteString] UTF8String],
+                               format.empty() ? nullptr : format.c_str(),
+                               filterOptions.empty() ? nullptr : filterOptions.c_str());
+#else
     // The file is removed upon downloading.
     const std::string tmpDir = FileUtil::createRandomDir(JAILED_DOCUMENT_ROOT);
     // Prevent user inputting anything funny here.
@@ -881,6 +890,7 @@ bool ChildSession::downloadAs(const char* /*buffer*/, int /*length*/, const std:
 
     sendTextFrame("downloadas: jail=" + _jailId + " dir=" + tmpDir + " name=" + name +
                   " port=" + std::to_string(ClientPortNumber) + " id=" + id);
+#endif
     return true;
 }
 
diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index a427a31de..f13955200 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -27,6 +27,7 @@ L.Control.Menubar = L.Control.extend({
 					{name: _('Word 2003 Document (.doc)'), id: 'downloadas-doc', type: 'action'},
 					{name: _('Word Document (.docx)'), id: 'downloadas-docx', type: 'action'},
 					{name: _('Rich Text (.rtf)'), id: 'downloadas-rtf', type: 'action'}]},
+				{name: _('Save as PDF'), id: 'downloadas-pdf', mobileapp: true, type: 'action'},
 				{name: _('Sign document'), id: 'signdocument', type: 'action'},
 				{type: 'separator'},
 				{name: _('Close document'), id: 'closedocument', type: 'action'}
@@ -993,6 +994,9 @@ L.Control.Menubar = L.Control.extend({
 				if (menu[i].mobileapp == false && window.ThisIsAMobileApp) {
 					continue;
 				}
+				if (menu[i].mobileapp == true && !window.ThisIsAMobileApp) {
+					continue;
+				}
 				var ulItem = L.DomUtil.create('ul', '', liItem);
 				var subitemList = this._createMenu(menu[i].menu);
 				if (!subitemList.length) {
diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js
index 8e3e15cc9..52920171f 100644
--- a/loleaflet/src/control/Toolbar.js
+++ b/loleaflet/src/control/Toolbar.js
@@ -72,7 +72,8 @@ L.Map.include({
 			options = '';
 		}
 
-		this.showBusy(_('Downloading...'), false);
+		if (!window.ThisIsAMobileApp)
+			this.showBusy(_('Downloading...'), false);
 		this._socket.sendMessage('downloadas ' +
 			'name=' + encodeURIComponent(name) + ' ' +
 			'id=' + id + ' ' +
commit c5d6c7dd402da6987cd01f3c0759b28b3503d85c
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Mon Aug 19 18:41:55 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Mon Aug 19 18:42:02 2019 +0200

    tdf#126972: The "file icon" button in the menubar is useless in the iOS app
    
    In "real" Online, in a WOPI environment, it does something useful. But
    not in the iOS app. So no need to have it at all.
    
    Change-Id: I87a6b7badcba2899f850a1e15eae591e9ed8895c
    Reviewed-on: https://gerrit.libreoffice.org/77742
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index 5c6612d8d..a427a31de 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -563,7 +563,7 @@ L.Control.Menubar = L.Control.extend({
 		});
 		$('#main-menu').attr('tabindex', 0);
 
-		if (this._map._permission !== 'readonly') {
+		if (!window.ThisIsTheiOSApp && this._map._permission !== 'readonly') {
 			this._createFileIcon();
 		}
 	},
commit ce86a423e30d199f82fe7b7900ec09251358b1ec
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Mon Aug 19 18:35:29 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Mon Aug 19 17:57:15 2019 +0200

    tdf#126972: Don't fold the menubar in the iOS app on a tablet
    
    As the menubar is now then always visible in that case, no need to
    have the hamburger button in the toolbar either.
    
    Change-Id: Iec1ae28858ad994d008c294e5fa4069c5e9bc7ed
    Reviewed-on: https://gerrit.libreoffice.org/77740
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/js/toolbar.js b/loleaflet/js/toolbar.js
index bfc40b7eb..10057bb25 100644
--- a/loleaflet/js/toolbar.js
+++ b/loleaflet/js/toolbar.js
@@ -47,7 +47,10 @@ function _updateVisibilityForToolbar(toolbar) {
 	var toHide = [];
 
 	toolbar.items.forEach(function(item) {
-		if (((isMobile && item.mobile === false) || (isTablet && item.tablet === false) || (isDesktop && item.desktop === false) || (!window.ThisIsAMobileApp && item.mobilebrowser === false)) && !item.hidden) {
+		if (window.ThisIsTheiOSApp && isTablet && item.iosapptablet === false) {
+			toHide.push(item.id);
+		}
+		else if (((isMobile && item.mobile === false) || (isTablet && item.tablet === false) || (isDesktop && item.desktop === false) || (!window.ThisIsAMobileApp && item.mobilebrowser === false)) && !item.hidden) {
 			toHide.push(item.id);
 		}
 		else if (((isMobile && item.mobile === true) || (isTablet && item.tablet === true) || (isDesktop && item.desktop === true) || (window.ThisIsAMobileApp && item.mobilebrowser === true)) && item.hidden) {
@@ -818,7 +821,7 @@ function createToolbar() {
 		{type: 'button',  id: 'sidebar', img: 'sidebar_modify_page', hint: _UNO('.uno:Sidebar', '', true), uno: '.uno:Sidebar', hidden: true},
 		{type: 'break', id: 'breaksidebar', hidden: true},
 		{type: 'button',  id: 'fold',  img: 'fold', desktop: true, mobile: false, hidden: true},
-		{type: 'button',  id: 'hamburger-tablet',  img: 'hamburger', desktop: false, mobile: false, tablet: true, hidden: true}
+		{type: 'button',  id: 'hamburger-tablet',  img: 'hamburger', desktop: false, mobile: false, tablet: true, iosapptablet: false, hidden: true}
 	];
 
 	if (_inMobileMode()) {
@@ -1733,7 +1736,7 @@ function onDocLayerInit() {
 	toolbarUp.refresh();
 	statusbar.refresh();
 
-	if (window.mode.isTablet()) {
+	if (!window.ThisIsTheiOSApp && window.mode.isTablet()) {
 		// Fold menubar by default
 		// FIXME: reuse toogleMenubar / use css
 		$('.main-nav').css({'display': 'none'});
commit 94bc1707cab5d0f5a91b82ca855a1107c199c7d1
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Fri Aug 16 18:09:58 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Mon Aug 19 10:16:57 2019 +0200

    tdf#126971: Fix localisation of tunnelled dialogs in the iOS app
    
    This used to work fine, but at some stage it had regressed. I did not
    bother bisecting to find the culprit. Anyway, now the JS part needs to
    send a lang parameter in the load message, too, for the corrent
    language to be used in the tunnelled dialogs. (Likely it affects also
    other things in core.)
    
    Change-Id: I339cddb28357978414669964106cb6fa472c967f
    Reviewed-on: https://gerrit.libreoffice.org/77599
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/js/global.js b/loleaflet/js/global.js
index d242b8f24..9d4a3ccc2 100644
--- a/loleaflet/js/global.js
+++ b/loleaflet/js/global.js
@@ -109,12 +109,17 @@
 	}
 
 	global.queueMsg = [];
+	if (window.ThisIsTheiOSApp)
+		window.LANG = window.getParameterByName('lang');
 	if (global.socket && global.socket.readyState !== 3) {
 		global.socket.onopen = function () {
 			if (global.socket.readyState === 1) {
 				var ProtocolVersionNumber = '0.1';
 				global.socket.send('loolclient ' + ProtocolVersionNumber);
-				global.socket.send('load url=' + encodeURIComponent(global.docURL));
+				if (window.ThisIsTheiOSApp)
+					global.socket.send('load url=' + encodeURIComponent(global.docURL) + ' lang=' + window.LANG);
+				else
+					global.socket.send('load url=' + encodeURIComponent(global.docURL));
 			}
 		}
 
diff --git a/loleaflet/util/create-l10n-all-js.pl b/loleaflet/util/create-l10n-all-js.pl
index 73e6ee68e..dc7227f78 100644
--- a/loleaflet/util/create-l10n-all-js.pl
+++ b/loleaflet/util/create-l10n-all-js.pl
@@ -29,8 +29,6 @@ sub insert($) {
 # woefully incomplete translation is worse than no translation at all.
 
 print "\
-window.LANG = window.getParameterByName('lang');
-
 //window.postMobileDebug('LANG is ' + window.LANG);
 
 var onlylang = window.LANG;
commit b4eed2f66514b7a3e9bec438075c9c6e544d1675
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sun Aug 18 10:22:21 2019 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Mon Aug 19 02:35:21 2019 +0200

    table handles: drag only in x/y axis, marker on hover, cursor
    
    This adds:
    - support to freeze movement to x or y axis when dragging the
    marker (depends on the marker type - column or row marker)
    
    - change marker on hover, which uses a different image, which is
    solved in css
    
    - change cursor to col-resize / row-resize when howering over the
    marker
    
    Change-Id: I63bf5e82860ef75f2dfde31ee2ab7ede6f61ce70
    Reviewed-on: https://gerrit.libreoffice.org/77652
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 7467710dab48d30fc3dcee66fc5a2fdec46184ae)
    Reviewed-on: https://gerrit.libreoffice.org/77683
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/loleaflet/css/loleaflet.css b/loleaflet/css/loleaflet.css
index 2178d2eea..a270af77a 100644
--- a/loleaflet/css/loleaflet.css
+++ b/loleaflet/css/loleaflet.css
@@ -53,6 +53,18 @@
 	background-image: url('images/table-column-resize-marker.svg');
 	background-size: 100% 100%;
 	background-repeat: no-repeat;
+	cursor: col-resize;
+}
+
+.table-column-resize-marker:hover {
+	margin-left: 0px;
+	margin-top: 0px;
+	width: 24px;
+	height: 24px;
+	background-image: url('images/table-column-resize-marker-hover.svg');
+	background-size: 100% 100%;
+	background-repeat: no-repeat;
+	cursor: col-resize;
 }
 
 .table-row-resize-marker {
@@ -63,6 +75,18 @@
 	background-image: url('images/table-row-resize-marker.svg');
 	background-size: 100% 100%;
 	background-repeat: no-repeat;
+	cursor: row-resize;
+}
+
+.table-row-resize-marker:hover {
+	margin-left: 0px;
+	margin-top: 0px;
+	width: 24px;
+	height: 24px;
+	background-image: url('images/table-row-resize-marker-hover.svg');
+	background-size: 100% 100%;
+	background-repeat: no-repeat;
+	cursor: row-resize;
 }
 
 body {
diff --git a/loleaflet/images/table-column-resize-marker-hover.svg b/loleaflet/images/table-column-resize-marker-hover.svg
new file mode 100644
index 000000000..a805d05ae
--- /dev/null
+++ b/loleaflet/images/table-column-resize-marker-hover.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
+ <g transform="matrix(0 -.70331 .70329 0 4.7475 27.253)" fill="#fff" fill-opacity=".86275" stroke="#38f" stroke-linecap="round">
+  <rect x="2.5185" y="2.5185" width="26.963" height="26.963" rx="4.4235" ry="4.4236" stroke-width="1.4745"/>
+  <g stroke-width="1.4219">
+   <rect x="8.5" y="8.5" width="15" height="1"/>
+   <rect x="8.5" y="15.5" width="15" height="1"/>
+   <rect x="8.5" y="22.5" width="15" height="1"/>
+  </g>
+ </g>
+</svg>
diff --git a/loleaflet/images/table-row-resize-marker-hover.svg b/loleaflet/images/table-row-resize-marker-hover.svg
new file mode 100644
index 000000000..7dab991ac
--- /dev/null
+++ b/loleaflet/images/table-row-resize-marker-hover.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
+ <g transform="matrix(.70331 0 0 .70329 4.7472 4.7474)" fill="#fff" fill-opacity=".86275" stroke="#38f" stroke-linecap="round">
+  <rect x="2.5185" y="2.5185" width="26.963" height="26.963" rx="4.4235" ry="4.4236" stroke-width="1.4745"/>
+  <g stroke-width="1.4219">
+   <rect x="8.5" y="8.5" width="15" height="1"/>
+   <rect x="8.5" y="15.5" width="15" height="1"/>
+   <rect x="8.5" y="22.5" width="15" height="1"/>
+  </g>
+ </g>
+</svg>
diff --git a/loleaflet/src/dom/Draggable.js b/loleaflet/src/dom/Draggable.js
index df22f3b11..d9f5485a8 100644
--- a/loleaflet/src/dom/Draggable.js
+++ b/loleaflet/src/dom/Draggable.js
@@ -25,6 +25,16 @@ L.Draggable = L.Evented.extend({
 		this._element = element;
 		this._dragStartTarget = dragStartTarget || element;
 		this._preventOutline = preventOutline;
+		this._freezeX = false;
+		this._freezeY = false;
+	},
+
+	freezeX: function (boolChoice) {
+		this._freezeX = boolChoice;
+	},
+
+	freezeY: function (boolChoice) {
+		this._freezeY = boolChoice;
 	},
 
 	enable: function () {
@@ -139,6 +149,12 @@ L.Draggable = L.Evented.extend({
 		}
 
 		this._newPos = this._startPos.add(offset);
+
+		if (this._freezeY)
+			this._newPos.y = this._startPos.y
+		if (this._freezeX)
+			this._newPos.x = this._startPos.x
+
 		this._moving = true;
 
 		L.Util.cancelAnimFrame(this._animRequest);
diff --git a/loleaflet/src/layer/marker/Marker.Drag.js b/loleaflet/src/layer/marker/Marker.Drag.js
index 5b879cd2b..d9f789235 100644
--- a/loleaflet/src/layer/marker/Marker.Drag.js
+++ b/loleaflet/src/layer/marker/Marker.Drag.js
@@ -44,6 +44,16 @@ L.Handler.MarkerDrag = L.Handler.extend({
 		return this._draggable && this._draggable._moved;
 	},
 
+	freezeX: function (boolChoice) {
+		if (this._draggable)
+			this._draggable.freezeX(boolChoice);
+	},
+
+	freezeY: function (boolChoice) {
+		if (this._draggable)
+			this._draggable.freezeY(boolChoice);
+	},
+
 	_onDown: function (e) {
 		this._marker.fire('down', e);
 	},
diff --git a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
index 169af9d8e..4ace14da0 100644
--- a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
+++ b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
@@ -19,6 +19,11 @@ L.TileLayer.include({
 			point = point.subtract(new L.Point(markerRect.width, markerRect.height / 2));
 		point = this._map.unproject(point);
 		marker.setLatLng(point);
+
+		if (marker._type.startsWith('column'))
+			marker.dragging.freezeY(true);
+		else
+			marker.dragging.freezeX(true);
 	},
 	_createMarker: function(markerType, entry, left, right) {
 		var className;
commit c2956383b9f353ffa98ae4a3c8e21769d3f334db
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Fri Aug 16 13:40:03 2019 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Fri Aug 16 13:06:27 2019 +0200

    tdf#122572: Make the context toolbar show up more reliably
    
    It seems that the _onPress function is sometimes called multiple times
    in succession and then the toolbar got first added but immediately
    removed again. Ugly hack to fix that.
    
    Change-Id: Id4f1569670e599a2b37afc9ae5d91f31661f72e2
    Reviewed-on: https://gerrit.libreoffice.org/77574
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loleaflet/src/map/handler/Map.TouchGesture.js b/loleaflet/src/map/handler/Map.TouchGesture.js
index 5f29ccb8b..87d206f6d 100644
--- a/loleaflet/src/map/handler/Map.TouchGesture.js
+++ b/loleaflet/src/map/handler/Map.TouchGesture.js
@@ -21,6 +21,7 @@ L.Map.TouchGesture = L.Handler.extend({
 
 		if (window.ThisIsTheiOSApp && !this._toolbar) {
 			this._toolbar = L.control.contextToolbar();
+			this._toolbarAdded = 0;
 		}
 
 		if (!this._hammer) {
@@ -155,10 +156,14 @@ L.Map.TouchGesture = L.Handler.extend({
 		    mousePos = this._map._docLayer._latLngToTwips(latlng);
 
 		if (window.ThisIsTheiOSApp) {
+			// console.log('==> ' + e.timeStamp);
 			if (!this._toolbar._map && this._map._docLayer.containsSelection(latlng)) {
 				this._toolbar._pos = containerPoint;
+				// console.log('==> Adding context toolbar ' + e.timeStamp);
 				this._toolbar.addTo(this._map);
-			} else {
+				this._toolbarAdded = e.timeStamp;
+			} else if (this._toolbarAdded && e.timeStamp - this._toolbarAdded >= 1000) {
+				// console.log('==> Removing context toolbar ' + e.timeStamp);
 				this._toolbar.remove();
 				this._map._contextMenu._onMouseDown({originalEvent: e.srcEvent});
 				// send right click to trigger context menus
commit 4c2b826e871b203e10b0cb73ca8126f77bbfdae6
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Wed Aug 14 18:13:40 2019 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Thu Aug 15 11:59:53 2019 +0200

    tdf#122529 Support for table overlay - column/row change markers
    
    This adds table markers for resizing rows and columns if the user
    has the table selected or the cursor is in the table. The code
    reacts to the callback "tableselected:", where the markers are
    created for each column and row, if the payload (json) of course
    has any data. When the marker is dragged, a uno command to resize
    the table column or row border is send to the core.
    
    Change-Id: I9b21d09639c1b2be70a1a897f9e3340b453d847e
    Reviewed-on: https://gerrit.libreoffice.org/77360
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit cc7060293945a6d45bf83376a456c57165a10f2f)
    Reviewed-on: https://gerrit.libreoffice.org/77486
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h b/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 9105eb547..75f496bb4 100644
--- a/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -665,6 +665,15 @@ typedef enum
      * Rectangle format is the same as LOK_CALLBACK_INVALIDATE_TILES.
      */
     LOK_CALLBACK_CELL_AUTO_FILL_AREA = 43,
+
+    /**
+     * When the cursor is in a table or a table is selected in the
+     * document, this sends the table's column and row border positions
+     * to the client. If the payload is empty (empty JSON object), then
+     * no table is currently selected or the cursor is not inside a table
+     * cell.
+     */
+    LOK_CALLBACK_TABLE_SELECTED = 44,
 }
 LibreOfficeKitCallbackType;
 
diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index 26ed99cce..2f66b67fd 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -2246,6 +2246,9 @@ void ChildSession::loKitCallback(const int type, const std::string& payload)
     case LOK_CALLBACK_CELL_AUTO_FILL_AREA:
         sendTextFrame("cellautofillarea: " + payload);
         break;
+    case LOK_CALLBACK_TABLE_SELECTED:
+        sendTextFrame("tableselected: " + payload);
+        break;
 
 #if !ENABLE_DEBUG
     // we want a compilation-time failure in the debug builds; but ERR in the
diff --git a/kit/KitHelper.hpp b/kit/KitHelper.hpp
index 7ef9f0207..defc4a5a6 100644
--- a/kit/KitHelper.hpp
+++ b/kit/KitHelper.hpp
@@ -137,6 +137,8 @@ namespace LOKitHelper
             return "CELL_SELECTION_AREA";
         case LOK_CALLBACK_CELL_AUTO_FILL_AREA:
             return "CELL_AUTO_FILL_AREA";
+        case LOK_CALLBACK_TABLE_SELECTED:
+            return "TABLE_SELECTED";
        }
 
         assert(!"Missing LOK_CALLBACK type");
diff --git a/loleaflet/Makefile.am b/loleaflet/Makefile.am
index 02a715fef..109cd85a5 100644
--- a/loleaflet/Makefile.am
+++ b/loleaflet/Makefile.am
@@ -346,6 +346,7 @@ pot:
 		src/errormessages.js \
 		src/layer/marker/Annotation.js \
 		src/layer/tile/TileLayer.js \
+		src/layer/tile/TileLayer.TableOverlay.js \
 		src/map/Map.js \
 		src/map/handler/Map.FileInserter.js \
 		src/map/handler/Map.WOPI.js
diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js
index 785eb7bb3..677a0a6be 100644
--- a/loleaflet/build/deps.js
+++ b/loleaflet/build/deps.js
@@ -45,7 +45,8 @@ var deps = {
 	},
 
 	TileLayer: {
-		src: ['layer/tile/TileLayer.js'],
+		src: ['layer/tile/TileLayer.js',
+			  'layer/tile/TileLayer.TableOverlay.js'],
 		desc: 'The base class for displaying tile layers on the map.',
 		deps: ['GridLayer']
 	},
diff --git a/loleaflet/css/loleaflet.css b/loleaflet/css/loleaflet.css
index 0b0c28b7d..2178d2eea 100644
--- a/loleaflet/css/loleaflet.css
+++ b/loleaflet/css/loleaflet.css
@@ -45,6 +45,26 @@
 	-ms-filter: "alpha(opacity=100)" !important;
 }
 
+.table-column-resize-marker {
+	margin-left: 0px;
+	margin-top: 0px;
+	width: 24px;
+	height: 24px;
+	background-image: url('images/table-column-resize-marker.svg');
+	background-size: 100% 100%;
+	background-repeat: no-repeat;
+}
+
+.table-row-resize-marker {
+	margin-left: 0px;
+	margin-top: 0px;
+	width: 24px;
+	height: 24px;
+	background-image: url('images/table-row-resize-marker.svg');
+	background-size: 100% 100%;
+	background-repeat: no-repeat;
+}
+
 body {
 	margin: 0;
 	overflow: hidden;
diff --git a/loleaflet/images/table-column-resize-marker.svg b/loleaflet/images/table-column-resize-marker.svg
new file mode 100644
index 000000000..2eefb752c
--- /dev/null
+++ b/loleaflet/images/table-column-resize-marker.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
+ <g transform="matrix(0 -.70331 .70329 0 4.7475 27.253)" fill="#fff" fill-opacity=".86275" stroke="#000" stroke-linecap="round">
+  <rect x="2.5185" y="2.5185" width="26.963" height="26.963" rx="4.4235" ry="4.4236" stroke-width="1.4745"/>
+  <g stroke-width="1.4219">
+   <rect x="8.5" y="8.5" width="15" height="1"/>
+   <rect x="8.5" y="15.5" width="15" height="1"/>
+   <rect x="8.5" y="22.5" width="15" height="1"/>
+  </g>
+ </g>
+</svg>
diff --git a/loleaflet/images/table-row-resize-marker.svg b/loleaflet/images/table-row-resize-marker.svg
new file mode 100644
index 000000000..812a38d43
--- /dev/null
+++ b/loleaflet/images/table-row-resize-marker.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
+ <g transform="matrix(.70331 0 0 .70329 4.7472 4.7474)" fill="#fff" fill-opacity=".86275" stroke="#000" stroke-linecap="round">
+  <rect x="2.5185" y="2.5185" width="26.963" height="26.963" rx="4.4235" ry="4.4236" stroke-width="1.4745"/>
+  <g stroke-width="1.4219">
+   <rect x="8.5" y="8.5" width="15" height="1"/>
+   <rect x="8.5" y="15.5" width="15" height="1"/>
+   <rect x="8.5" y="22.5" width="15" height="1"/>
+  </g>
+ </g>
+</svg>
diff --git a/loleaflet/src/layer/tile/TileLayer.TableOverlay.js b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
new file mode 100644
index 000000000..169af9d8e
--- /dev/null
+++ b/loleaflet/src/layer/tile/TileLayer.TableOverlay.js
@@ -0,0 +1,191 @@
+/* -*- js-indent-level: 8 -*- */
+/*
+ * Table Overlay
+ */
+
+L.TileLayer.include({
+	_initializeTableOverlay: function () {
+		this._tableColumnMarkers = [];
+		this._tableRowMarkers = [];
+		this._tableMarkersDragged = false;
+	},
+	_setMarkerPosition: function(marker) {
+		var point = this._twipsToLatLng(marker._pointTwips, this._map.getZoom());
+		point = this._map.project(point);
+		var markerRect = marker._icon.getBoundingClientRect();
+		if (marker._type.startsWith('column'))
+			point = point.subtract(new L.Point(markerRect.width / 2, markerRect.height));
+		else
+			point = point.subtract(new L.Point(markerRect.width, markerRect.height / 2));
+		point = this._map.unproject(point);
+		marker.setLatLng(point);
+	},
+	_createMarker: function(markerType, entry, left, right) {
+		var className;
+		if (markerType === 'column')
+			className = 'table-column-resize-marker';
+		else
+			className = 'table-row-resize-marker';
+
+		var marker = L.marker(new L.LatLng(0, 0), {
+			icon: L.divIcon({
+				className: className,
+				iconSize: null
+			}),
+			draggable: true
+		});
+		this._map.addLayer(marker);
+		marker._type = markerType + '-' + entry.type;
+		marker._position = parseInt(entry.position);
+		marker._min = parseInt(entry.min);
+		marker._max = parseInt(entry.max);
+		marker._index = parseInt(entry.index);
+		if (markerType === 'column') {
+			marker._pointTwips = new L.Point(this._tablePositionColumnOffset + marker._position, left);
+			marker._pointTop = new L.Point(this._tablePositionColumnOffset + marker._position, left);
+			marker._pointTop = this._twipsToLatLng(marker._pointTop, this._map.getZoom());
+			marker._pointBottom = new L.Point(this._tablePositionColumnOffset + marker._position, right);
+			marker._pointBottom = this._twipsToLatLng(marker._pointBottom, this._map.getZoom());
+		}
+		else {
+			marker._pointTwips = new L.Point(left, this._tablePositionRowOffset + marker._position);
+			marker._pointTop = new L.Point(left, this._tablePositionRowOffset + marker._position);
+			marker._pointTop = this._twipsToLatLng(marker._pointTop, this._map.getZoom());
+			marker._pointBottom = new L.Point(right, this._tablePositionRowOffset + marker._position);
+			marker._pointBottom = this._twipsToLatLng(marker._pointBottom, this._map.getZoom());
+		}
+		this._setMarkerPosition(marker);
+		marker.on('dragstart drag dragend', this._onTableResizeMarkerDrag, this);
+		return marker;
+	},
+	_onTableSelectedMsg: function (textMsg) {
+		if (this._tableMarkersDragged == true) {
+			return;
+		}
+
+		// Clean-up first
+		var markerIndex;
+		for (markerIndex = 0; markerIndex < this._tableColumnMarkers.length; markerIndex++) {
+			this._map.removeLayer(this._tableColumnMarkers[markerIndex]);
+		}
+		this._tableColumnMarkers = [];
+
+		for (markerIndex = 0; markerIndex < this._tableRowMarkers.length; markerIndex++) {
+			this._map.removeLayer(this._tableRowMarkers[markerIndex]);
+		}
+		this._tableRowMarkers = [];
+
+		// Parse the message
+		textMsg = textMsg.substring('tableselected:'.length + 1);
+		var message = JSON.parse(textMsg);
+
+		// Create markers

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list