diff options
-rw-r--r-- | common/AppDocument.cpp | 176 | ||||
-rw-r--r-- | common/AppDocument.hpp | 50 | ||||
-rw-r--r-- | ios/Mobile.xcodeproj/project.pbxproj | 100 | ||||
-rw-r--r-- | ios/Mobile/AppDelegate.h | 2 | ||||
-rw-r--r-- | ios/Mobile/AppDelegate.mm | 72 | ||||
-rw-r--r-- | ios/Mobile/COAppDocument.hpp | 32 | ||||
-rw-r--r-- | ios/Mobile/COAppDocument.mm | 42 | ||||
-rw-r--r-- | ios/Mobile/CODocument.h | 12 | ||||
-rw-r--r-- | ios/Mobile/CODocument.mm | 49 | ||||
-rw-r--r-- | ios/Mobile/DocumentBrowserViewController.mm | 1 | ||||
-rw-r--r-- | ios/Mobile/DocumentViewController.mm | 105 | ||||
-rw-r--r-- | ios/Mobile/TemplateCollectionViewController.mm | 5 | ||||
-rw-r--r-- | ios/ios.h | 4 | ||||
-rw-r--r-- | ios/ios.mm | 2 | ||||
-rw-r--r-- | kit/Kit.cpp | 27 | ||||
-rw-r--r-- | kit/Kit.hpp | 4 |
16 files changed, 406 insertions, 277 deletions
diff --git a/common/AppDocument.cpp b/common/AppDocument.cpp new file mode 100644 index 0000000000..635336e10c --- /dev/null +++ b/common/AppDocument.cpp @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <string> + +#include "AppDocument.hpp" +#include "KitHelper.hpp" +#include "Log.hpp" +#include "Protocol.hpp" +#include "RenderTiles.hpp" +#include "Util.hpp" + +static void messageQueueThreadFunction(AppDocument *document) +{ + PngCache pngCache; + ThreadPool pngPool; + + LOG_ERR("messageQueueThreadFunction " << document->getAppDocId() << " started"); + + Util::setThreadName("message_queue_" + std::to_string(document->getAppDocId())); + + while (true) { + TileQueue::Payload message = document->getTileQueue()->get(); + if (std::strcmp(message.data(), "closedocument") == 0) + break; + + const std::string firstLine = LOOLProtocol::getFirstLine(message.data(), message.size()); + const StringVector tokens = Util::tokenize(firstLine.data(), firstLine.size()); + LOG_INF("Handling " << tokens[0]); + if (tokens.equals(0, "tile") || + tokens.equals(0, "tilecombine")) + { + TileCombined tileCombined(TileCombined::parse(tokens)); + if (!RenderTiles::doRender(document->getLoKitDoc(), tileCombined, pngCache, pngPool, false, + [&](unsigned char *, + int, int, + size_t, size_t, + int, int, + LibreOfficeKitTileMode) { + // Nothing + }, + [&](const char *buffer, size_t length) { + document->sendMessageToJS(buffer, length); + } + )) + { + LOG_ERR("Rendering tiles failed"); + } + } + else + { + LOG_ERR("Unhandled " << tokens[0]); + } + } + LOG_ERR("messageQueueThreadFunction " << document->getAppDocId() << " finishing"); +} + +std::atomic<int> AppDocument::appDocIdCounter(1); + +AppDocument::AppDocument(std::shared_ptr<lok::Office> theLoKit) + : loKit(theLoKit), + tileQueue(std::make_shared<TileQueue>()), + appDocId(appDocIdCounter++), + messageQueueThread(std::thread(messageQueueThreadFunction, this)) +{ +} + +static void docCallback(const int type, const char* p, void* data) +{ + LOG_INF("docCallback: " << lokCallbackTypeToString(type) << (p ? p : "(null")); + + AppDocument* document = (AppDocument*)data; + + switch (type) { + case LOK_CALLBACK_INVALIDATE_TILES: + break; + } +} + +void AppDocument::handleProtocolMessage(const char* buffer, int length) +{ + const std::string firstLine = LOOLProtocol::getFirstLine(buffer, length); + const StringVector tokens = Util::tokenize(firstLine.data(), firstLine.size()); + + if (tokens.equals(0, "loolclient")) + { + if (tokens.size() < 2) + { + sendMessageToJS("error: cmd=loolclient kind=badprotocolversion"); + return; + } + + const std::tuple<int, int, std::string> versionTuple = LOOLProtocol::ParseVersion(tokens[1]); + if (std::get<0>(versionTuple) != LOOLProtocol::ProtocolMajorVersionNumber || + std::get<1>(versionTuple) != LOOLProtocol::ProtocolMinorVersionNumber) + { + sendMessageToJS("error: cmd=loolclient kind=badprotocolversion"); + return; + } + + // Send LOOL version information + sendMessageToJS("loolserver " + Util::getVersionJSON()); + // Send LOKit version information + sendMessageToJS("lokitversion " + std::string(loKit->getVersionInfo())); + } + else if (tokens.equals(0, "jserror")) + { + LOG_ERR(std::string(buffer, length)); + return; + } + else if (tokens.equals(0, "load")) + { + loKitDoc.reset(loKit->documentLoad(getDocumentURL().c_str(), "")); + sendMessageToJS("statusindicator: find"); + sendMessageToJS("statusindicator: connect"); + sendMessageToJS("statusindicator: ready"); + sendMessageToJS("loolserver " + Util::getVersionJSON()); + sendMessageToJS("lokitversion " + std::string(loKit->getVersionInfo())); + sendMessageToJS("statusindicatorsetvalue: 100"); + sendMessageToJS("statusindicatorstart:"); + sendMessageToJS("status: " + LOKitHelper::documentStatus(loKitDoc->get())); + sendMessageToJS("statusindicatorfinish:"); + + loKitDoc->initializeForRendering(""); + int viewId = loKitDoc->getView(); + loKitDoc->setViewLanguage(viewId, getAppLocale().c_str()); + loKitDoc->registerCallback(docCallback, this); + } + else if (tokens.equals(0, "closedocument") || + tokens.equals(0, "tile") || + tokens.equals(0, "tilecombine")) + { + tileQueue->put(std::string(buffer)); + } + else if (tokens.equals(0, "canceltiles") || + tokens.equals(0, "clientvisiblearea") || + tokens.equals(0, "clientzoom") || + tokens.equals(0, "renderfont") || + tokens.equals(0, "save") || + tokens.equals(0, "status") || + tokens.equals(0, "statusupdate")) + { + LOG_WRN("Not yet implemented: " << tokens[0]); + } + else if (tokens.equals(0, "xxx")) + { + LOG_WRN("Ignoring: " << tokens[0]); + } + else + { + LOG_ERR("Unrecognized: " << tokens[0]); + } +} + +std::shared_ptr<lok::Document> AppDocument::getLoKitDoc() const +{ + return loKitDoc; +} + +std::shared_ptr<TileQueue> AppDocument::getTileQueue() const +{ + return tileQueue; +} + +int AppDocument::getAppDocId() const +{ + return appDocId; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/common/AppDocument.hpp b/common/AppDocument.hpp new file mode 100644 index 0000000000..0de0070428 --- /dev/null +++ b/common/AppDocument.hpp @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <memory> +#include <string> +#include <thread> + +#define LOK_USE_UNSTABLE_API +#include <LibreOfficeKit/LibreOfficeKit.hxx> + +#include "MessageQueue.hpp" +#include "TileDesc.hpp" + +// The C++ document-specific data in the next-gen iOS (and Android?) app. +class AppDocument +{ +public: + AppDocument(std::shared_ptr<lok::Office> theLoKit); + + void handleProtocolMessage(const char* buffer, int length); + std::shared_ptr<lok::Document> getLoKitDoc() const; + std::shared_ptr<TileQueue> getTileQueue() const; + int getAppDocId() const; + + virtual void sendMessageToJS(std::string) = 0; + virtual void sendMessageToJS(const char* buffer, int length) = 0; + +protected: + virtual std::string getDocumentURL() = 0; + virtual std::string getAppLocale() = 0; + +private: + std::shared_ptr<lok::Office> loKit; + std::shared_ptr<lok::Document> loKitDoc; + std::shared_ptr<TileQueue> tileQueue; + + static std::atomic<int> appDocIdCounter; + const int appDocId; + std::thread messageQueueThread; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ios/Mobile.xcodeproj/project.pbxproj b/ios/Mobile.xcodeproj/project.pbxproj index a15dda8fc5..924197d5fc 100644 --- a/ios/Mobile.xcodeproj/project.pbxproj +++ b/ios/Mobile.xcodeproj/project.pbxproj @@ -17,19 +17,14 @@ BE18C7DE226DE09A001AD27E /* Branding in Resources */ = {isa = PBXBuildFile; fileRef = BE18C7DD226DE09A001AD27E /* Branding */; }; BE5EB5C1213FE29900E0826C /* Log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5B9213FE29900E0826C /* Log.cpp */; }; BE5EB5C2213FE29900E0826C /* SpookyV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5BA213FE29900E0826C /* SpookyV2.cpp */; }; - BE5EB5C3213FE29900E0826C /* Session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5BB213FE29900E0826C /* Session.cpp */; }; BE5EB5C4213FE29900E0826C /* Util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5BC213FE29900E0826C /* Util.cpp */; }; BE5EB5C5213FE29900E0826C /* MessageQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5BD213FE29900E0826C /* MessageQueue.cpp */; }; BE5EB5C6213FE29900E0826C /* SigUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5BE213FE29900E0826C /* SigUtil.cpp */; }; BE5EB5C7213FE29900E0826C /* Protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5BF213FE29900E0826C /* Protocol.cpp */; }; - BE5EB5C8213FE29900E0826C /* FileUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5C0213FE29900E0826C /* FileUtil.cpp */; }; - BE5EB5CF213FE2D000E0826C /* ClientSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5CC213FE2D000E0826C /* ClientSession.cpp */; }; - BE5EB5D0213FE2D000E0826C /* TileCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5CD213FE2D000E0826C /* TileCache.cpp */; }; - BE5EB5D22140039100E0826C /* LOOLWSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5D12140039100E0826C /* LOOLWSD.cpp */; }; - BE5EB5D421400DC100E0826C /* DocumentBroker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5D321400DC100E0826C /* DocumentBroker.cpp */; }; - BE5EB5D621401E0F00E0826C /* Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5D521401E0F00E0826C /* Storage.cpp */; }; BE5EB5DA2140363100E0826C /* ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = BE5EB5D92140363100E0826C /* ios.mm */; }; BE5EB5DC2140480B00E0826C /* ICU.dat in Resources */ = {isa = PBXBuildFile; fileRef = BE5EB5DB2140480B00E0826C /* ICU.dat */; }; + BE62A58724BEE1F600AFFD77 /* AppDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE62A58624BEE1F500AFFD77 /* AppDocument.cpp */; }; + BE62A58A24BEE55200AFFD77 /* COAppDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = BE62A58924BEE55100AFFD77 /* COAppDocument.mm */; }; BE6362C22153B5B500F4237E /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE6362C12153B5B500F4237E /* MobileCoreServices.framework */; }; BE7228E22417BC9F000ADABD /* StringVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE7228E02417BC9F000ADABD /* StringVector.cpp */; }; BE7D6A6B23FAA8B500C2E605 /* loolkitconfig.xcu in Resources */ = {isa = PBXBuildFile; fileRef = BE7D6A6A23FAA8B500C2E605 /* loolkitconfig.xcu */; }; @@ -56,15 +51,8 @@ BE8D85D4214055F3009F1860 /* fundamentalrc in Resources */ = {isa = PBXBuildFile; fileRef = BE8D85C6214055F3009F1860 /* fundamentalrc */; }; BE8D85D5214055F3009F1860 /* unorc in Resources */ = {isa = PBXBuildFile; fileRef = BE8D85C7214055F3009F1860 /* unorc */; }; BE8D85D6214055F3009F1860 /* rc in Resources */ = {isa = PBXBuildFile; fileRef = BE8D85C8214055F3009F1860 /* rc */; }; - BEA2835621467FDD00848631 /* Kit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEA2835521467FDD00848631 /* Kit.cpp */; }; - BEA283582146945500848631 /* ChildSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEA283572146945500848631 /* ChildSession.cpp */; }; BEA2835A21470A1C00848631 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEA2835921470A1C00848631 /* WebKit.framework */; }; - BEA2835D21498AD400848631 /* Socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEA2835C21498AD400848631 /* Socket.cpp */; }; - BEA28360214ACA8500848631 /* FakeSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEA2835F214ACA8500848631 /* FakeSocket.cpp */; }; - BEA28377214FFD8C00848631 /* Unit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEA28376214FFD8C00848631 /* Unit.cpp */; }; - BEABFC6824AC94C3004DE339 /* Authorization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEABFC6624AC94C3004DE339 /* Authorization.cpp */; }; BEB0E5D921C7CA800085A0CF /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BEB0E5D821C7CA800085A0CF /* Settings.bundle */; }; - BEBF3EB0246EB1C800415E87 /* RequestDetails.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEBF3EAF246EB1C800415E87 /* RequestDetails.cpp */; }; BECD984024336DD400016117 /* device-mobile.css in Resources */ = {isa = PBXBuildFile; fileRef = BECD983E24336DD400016117 /* device-mobile.css */; }; BECD984124336DD400016117 /* device-tablet.css in Resources */ = {isa = PBXBuildFile; fileRef = BECD983F24336DD400016117 /* device-tablet.css */; }; BEDCC84E2452F82800FB02BD /* MobileApp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEDCC84C2452F82800FB02BD /* MobileApp.cpp */; }; @@ -80,6 +68,8 @@ BE00F89E21396585001CE2D4 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; name = images; path = ../../../loleaflet/dist/images; sourceTree = "<group>"; }; BE00F8B4213ED543001CE2D4 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; BE00F8B6213ED573001CE2D4 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + BE04F4DA24B86E8E0079A1FB /* KitHelper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = KitHelper.hpp; sourceTree = "<group>"; }; + BE04F4DB24B895780079A1FB /* TileDesc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TileDesc.hpp; sourceTree = "<group>"; }; BE18C7DD226DE09A001AD27E /* Branding */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Branding; path = Mobile/Branding; sourceTree = SOURCE_ROOT; }; BE28F880228CE04600C00C48 /* langselect.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = langselect.hxx; path = "../../ios-device/desktop/source/app/langselect.hxx"; sourceTree = "<group>"; }; BE28F881228CE04600C00C48 /* officeipcthread.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = officeipcthread.hxx; path = "../../ios-device/desktop/source/app/officeipcthread.hxx"; sourceTree = "<group>"; }; @@ -477,7 +467,6 @@ BE484B6E228CF36E001EE76C /* configvaluecontainer.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = configvaluecontainer.cxx; path = "../../ios-device/unotools/source/config/configvaluecontainer.cxx"; sourceTree = "<group>"; }; BE484B6F228CF36E001EE76C /* bootstrap.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bootstrap.cxx; path = "../../ios-device/unotools/source/config/bootstrap.cxx"; sourceTree = "<group>"; }; BE484B70228CF36E001EE76C /* saveopt.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = saveopt.cxx; path = "../../ios-device/unotools/source/config/saveopt.cxx"; sourceTree = "<group>"; }; - BE484B71228D8622001EE76C /* DocumentBroker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DocumentBroker.hpp; sourceTree = "<group>"; }; BE484B732292AF96001EE76C /* frmload.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = frmload.cxx; path = "../../ios-device/sfx2/source/view/frmload.cxx"; sourceTree = "<group>"; }; BE484B742292AF96001EE76C /* sfxbasecontroller.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = sfxbasecontroller.cxx; path = "../../ios-device/sfx2/source/view/sfxbasecontroller.cxx"; sourceTree = "<group>"; }; BE484B752292AF96001EE76C /* frame.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = frame.cxx; path = "../../ios-device/sfx2/source/view/frame.cxx"; sourceTree = "<group>"; }; @@ -503,7 +492,6 @@ BE58E12C217F295B00249358 /* Util.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Util.hpp; sourceTree = "<group>"; }; BE58E12D217F295B00249358 /* MessageQueue.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MessageQueue.hpp; sourceTree = "<group>"; }; BE58E12E217F295B00249358 /* Protocol.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Protocol.hpp; sourceTree = "<group>"; }; - BE58E12F217F295B00249358 /* Session.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Session.hpp; sourceTree = "<group>"; }; BE58E13021874A2E00249358 /* Mobile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Mobile.entitlements; sourceTree = "<group>"; }; BE58E132218793B500249358 /* svpbmp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpbmp.cxx; path = "../../ios-device/vcl/headless/svpbmp.cxx"; sourceTree = "<group>"; }; BE58E133218793B500249358 /* svpglyphcache.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpglyphcache.cxx; path = "../../ios-device/vcl/headless/svpglyphcache.cxx"; sourceTree = "<group>"; }; @@ -519,20 +507,16 @@ BE58E13D218793B600249358 /* svpframe.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svpframe.cxx; path = "../../ios-device/vcl/headless/svpframe.cxx"; sourceTree = "<group>"; }; BE5EB5B9213FE29900E0826C /* Log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Log.cpp; sourceTree = "<group>"; }; BE5EB5BA213FE29900E0826C /* SpookyV2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpookyV2.cpp; sourceTree = "<group>"; }; - BE5EB5BB213FE29900E0826C /* Session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Session.cpp; sourceTree = "<group>"; }; BE5EB5BC213FE29900E0826C /* Util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Util.cpp; sourceTree = "<group>"; }; BE5EB5BD213FE29900E0826C /* MessageQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessageQueue.cpp; sourceTree = "<group>"; }; BE5EB5BE213FE29900E0826C /* SigUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SigUtil.cpp; sourceTree = "<group>"; }; BE5EB5BF213FE29900E0826C /* Protocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Protocol.cpp; sourceTree = "<group>"; }; - BE5EB5C0213FE29900E0826C /* FileUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileUtil.cpp; sourceTree = "<group>"; }; - BE5EB5CC213FE2D000E0826C /* ClientSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientSession.cpp; sourceTree = "<group>"; }; - BE5EB5CD213FE2D000E0826C /* TileCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TileCache.cpp; sourceTree = "<group>"; }; - BE5EB5D12140039100E0826C /* LOOLWSD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LOOLWSD.cpp; sourceTree = "<group>"; }; - BE5EB5D321400DC100E0826C /* DocumentBroker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentBroker.cpp; sourceTree = "<group>"; }; - BE5EB5D521401E0F00E0826C /* Storage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Storage.cpp; sourceTree = "<group>"; }; BE5EB5D92140363100E0826C /* ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios.mm; path = ../../ios/ios.mm; sourceTree = "<group>"; }; BE5EB5DB2140480B00E0826C /* ICU.dat */ = {isa = PBXFileReference; lastKnownFileType = file; name = ICU.dat; path = ../../../ICU.dat; sourceTree = "<group>"; }; - BE636210215101D000F4237E /* WebSocketHandler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = WebSocketHandler.hpp; sourceTree = "<group>"; }; + BE62A58524BEE1F500AFFD77 /* AppDocument.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AppDocument.hpp; sourceTree = "<group>"; }; + BE62A58624BEE1F500AFFD77 /* AppDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppDocument.cpp; sourceTree = "<group>"; }; + BE62A58824BEE55100AFFD77 /* COAppDocument.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = COAppDocument.hpp; sourceTree = "<group>"; }; + BE62A58924BEE55100AFFD77 /* COAppDocument.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = COAppDocument.mm; sourceTree = "<group>"; }; BE6362C12153B5B500F4237E /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; BE7228E02417BC9F000ADABD /* StringVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringVector.cpp; sourceTree = "<group>"; }; BE7228E12417BC9F000ADABD /* StringVector.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StringVector.hpp; sourceTree = "<group>"; }; @@ -779,7 +763,7 @@ BE8C03C32242BA680048B7EA /* appdata.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = appdata.cxx; path = "../../ios-device/sfx2/source/appl/appdata.cxx"; sourceTree = "<group>"; }; BE8C03C42242BA680048B7EA /* shellimpl.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = shellimpl.cxx; path = "../../ios-device/sfx2/source/appl/shellimpl.cxx"; sourceTree = "<group>"; }; BE8C03C52242BA680048B7EA /* panelist.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = panelist.hxx; path = "../../ios-device/sfx2/source/appl/panelist.hxx"; sourceTree = "<group>"; }; - BE8D77272136762500AC58EA /* Mobile.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Mobile.app; sourceTree = BUILT_PRODUCTS_DIR; }; + BE8D77272136762500AC58EA /* Collabora Office2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Collabora Office2.app"; sourceTree = BUILT_PRODUCTS_DIR; }; BE8D772A2136762500AC58EA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; BE8D772B2136762500AC58EA /* AppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AppDelegate.mm; sourceTree = "<group>"; }; BE8D772D2136762500AC58EA /* DocumentBrowserViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DocumentBrowserViewController.h; sourceTree = "<group>"; }; @@ -975,14 +959,7 @@ BE93D46A216D5582007A39F4 /* watermarkitem.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = watermarkitem.cxx; path = "../../ios-device/sfx2/source/doc/watermarkitem.cxx"; sourceTree = "<group>"; }; BE93D46B216D5582007A39F4 /* new.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = new.cxx; path = "../../ios-device/sfx2/source/doc/new.cxx"; sourceTree = "<group>"; }; BE93D46C216D5582007A39F4 /* objembed.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = objembed.cxx; path = "../../ios-device/sfx2/source/doc/objembed.cxx"; sourceTree = "<group>"; }; - BEA2835521467FDD00848631 /* Kit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Kit.cpp; sourceTree = "<group>"; }; - BEA283572146945500848631 /* ChildSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ChildSession.cpp; sourceTree = "<group>"; }; BEA2835921470A1C00848631 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - BEA2835C21498AD400848631 /* Socket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Socket.cpp; path = ../net/Socket.cpp; sourceTree = "<group>"; }; - BEA2835E214A8E2000848631 /* Socket.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Socket.hpp; sourceTree = "<group>"; }; - BEA2835F214ACA8500848631 /* FakeSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FakeSocket.cpp; sourceTree = "<group>"; }; - BEA28376214FFD8C00848631 /* Unit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Unit.cpp; sourceTree = "<group>"; }; - BEA283782150172600848631 /* Unit.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Unit.hpp; sourceTree = "<group>"; }; BEA8CD7421959342009FE17E /* caserotate.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = caserotate.cxx; path = "../../ios-device/unotools/source/i18n/caserotate.cxx"; sourceTree = "<group>"; }; BEA8CD7521959342009FE17E /* intlwrapper.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = intlwrapper.cxx; path = "../../ios-device/unotools/source/i18n/intlwrapper.cxx"; sourceTree = "<group>"; }; BEA8CD7621959342009FE17E /* transliterationwrapper.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = transliterationwrapper.cxx; path = "../../ios-device/unotools/source/i18n/transliterationwrapper.cxx"; sourceTree = "<group>"; }; @@ -997,8 +974,6 @@ BEA8CDC32199AC9D009FE17E /* lok.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = lok.cxx; path = "../../ios-device/comphelper/source/misc/lok.cxx"; sourceTree = "<group>"; }; BEA8CDC52199E621009FE17E /* languagetagicu.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = languagetagicu.cxx; path = "../../ios-device/i18nlangtag/source/languagetag/languagetagicu.cxx"; sourceTree = "<group>"; }; BEA8CDC62199E621009FE17E /* languagetag.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = languagetag.cxx; path = "../../ios-device/i18nlangtag/source/languagetag/languagetag.cxx"; sourceTree = "<group>"; }; - BEABFC6624AC94C3004DE339 /* Authorization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Authorization.cpp; sourceTree = "<group>"; }; - BEABFC6724AC94C3004DE339 /* Authorization.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Authorization.hpp; sourceTree = "<group>"; }; BEB0E5D821C7CA800085A0CF /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; }; BEB0E5DB21CA7C780085A0CF /* graphicfilter.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = graphicfilter.cxx; path = "../../ios-device/vcl/source/filter/graphicfilter.cxx"; sourceTree = "<group>"; }; BEB0E5E021CA9DC00085A0CF /* salbmp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salbmp.cxx; path = "../../ios-device/vcl/quartz/salbmp.cxx"; sourceTree = "<group>"; }; @@ -1060,8 +1035,6 @@ BEB6524E216FD0CA00B8C09A /* stream.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = stream.cxx; path = "../../ios-device/tools/source/stream/stream.cxx"; sourceTree = "<group>"; }; BEB6524F216FD0CA00B8C09A /* strmwnt.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = strmwnt.cxx; path = "../../ios-device/tools/source/stream/strmwnt.cxx"; sourceTree = "<group>"; }; BEB65250216FD0CA00B8C09A /* strmunx.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = strmunx.cxx; path = "../../ios-device/tools/source/stream/strmunx.cxx"; sourceTree = "<group>"; }; - BEBF3EAE246EB1C800415E87 /* RequestDetails.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RequestDetails.hpp; sourceTree = "<group>"; }; - BEBF3EAF246EB1C800415E87 /* RequestDetails.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RequestDetails.cpp; sourceTree = "<group>"; }; BECBD30323D7152900DA5582 /* SlsFramePainter.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SlsFramePainter.cxx; path = "../../ios-device/sd/source/ui/slidesorter/view/SlsFramePainter.cxx"; sourceTree = "<group>"; }; BECBD30423D7152900DA5582 /* SlideSorterView.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SlideSorterView.cxx; path = "../../ios-device/sd/source/ui/slidesorter/view/SlideSorterView.cxx"; sourceTree = "<group>"; }; BECBD30523D7152900DA5582 /* SlsFramePainter.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = SlsFramePainter.hxx; path = "../../ios-device/sd/source/ui/slidesorter/view/SlsFramePainter.hxx"; sourceTree = "<group>"; }; @@ -1889,9 +1862,8 @@ BE5EB5B6213FE21000E0826C /* common */ = { isa = PBXGroup; children = ( - BEABFC6624AC94C3004DE339 /* Authorization.cpp */, - BEABFC6724AC94C3004DE339 /* Authorization.hpp */, - BE5EB5C0213FE29900E0826C /* FileUtil.cpp */, + BE62A58624BEE1F500AFFD77 /* AppDocument.cpp */, + BE62A58524BEE1F500AFFD77 /* AppDocument.hpp */, BE5EB5B9213FE29900E0826C /* Log.cpp */, BE58E129217F295B00249358 /* Log.hpp */, BE5EB5BD213FE29900E0826C /* MessageQueue.cpp */, @@ -1901,15 +1873,11 @@ BE58E12A217F295B00249358 /* Png.hpp */, BE5EB5BF213FE29900E0826C /* Protocol.cpp */, BE58E12E217F295B00249358 /* Protocol.hpp */, - BE5EB5BB213FE29900E0826C /* Session.cpp */, - BE58E12F217F295B00249358 /* Session.hpp */, BE5EB5BE213FE29900E0826C /* SigUtil.cpp */, BE58E12B217F295B00249358 /* SigUtil.hpp */, BE5EB5BA213FE29900E0826C /* SpookyV2.cpp */, BE7228E02417BC9F000ADABD /* StringVector.cpp */, BE7228E12417BC9F000ADABD /* StringVector.hpp */, - BEA28376214FFD8C00848631 /* Unit.cpp */, - BEA283782150172600848631 /* Unit.hpp */, BE5EB5BC213FE29900E0826C /* Util.cpp */, BE58E12C217F295B00249358 /* Util.hpp */, ); @@ -1919,14 +1887,7 @@ BE5EB5B7213FE21600E0826C /* wsd */ = { isa = PBXGroup; children = ( - BEBF3EAF246EB1C800415E87 /* RequestDetails.cpp */, - BEBF3EAE246EB1C800415E87 /* RequestDetails.hpp */, - BE5EB5CC213FE2D000E0826C /* ClientSession.cpp */, - BE5EB5D321400DC100E0826C /* DocumentBroker.cpp */, - BE484B71228D8622001EE76C /* DocumentBroker.hpp */, - BE5EB5D12140039100E0826C /* LOOLWSD.cpp */, - BE5EB5D521401E0F00E0826C /* Storage.cpp */, - BE5EB5CD213FE2D000E0826C /* TileCache.cpp */, + BE04F4DB24B895780079A1FB /* TileDesc.hpp */, ); name = wsd; path = ../wsd; @@ -2268,7 +2229,7 @@ BE8D77282136762500AC58EA /* Products */ = { isa = PBXGroup; children = ( - BE8D77272136762500AC58EA /* Mobile.app */, + BE8D77272136762500AC58EA /* Collabora Office2.app */, ); name = Products; sourceTree = "<group>"; @@ -2276,6 +2237,8 @@ BE8D77292136762500AC58EA /* Mobile */ = { isa = PBXGroup; children = ( + BE62A58824BEE55100AFFD77 /* COAppDocument.hpp */, + BE62A58924BEE55100AFFD77 /* COAppDocument.mm */, BE58E13021874A2E00249358 /* Mobile.entitlements */, BE5EB5D92140363100E0826C /* ios.mm */, BE00F8922139494E001CE2D4 /* Resources */, @@ -2538,8 +2501,7 @@ BEA2835421467F8200848631 /* kit */ = { isa = PBXGroup; children = ( - BEA283572146945500848631 /* ChildSession.cpp */, - BEA2835521467FDD00848631 /* Kit.cpp */, + BE04F4DA24B86E8E0079A1FB /* KitHelper.hpp */, ); name = kit; path = ../kit; @@ -2548,10 +2510,6 @@ BEA2835B21498ABF00848631 /* net */ = { isa = PBXGroup; children = ( - BEA2835F214ACA8500848631 /* FakeSocket.cpp */, - BEA2835C21498AD400848631 /* Socket.cpp */, - BEA2835E214A8E2000848631 /* Socket.hpp */, - BE636210215101D000F4237E /* WebSocketHandler.hpp */, ); name = net; path = ../net; @@ -2957,7 +2915,7 @@ ); name = Mobile; productName = Mobile; - productReference = BE8D77272136762500AC58EA /* Mobile.app */; + productReference = BE8D77272136762500AC58EA /* Collabora Office2.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -3040,36 +2998,24 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - BEA2835D21498AD400848631 /* Socket.cpp in Sources */, BE5EB5C4213FE29900E0826C /* Util.cpp in Sources */, - BEA283582146945500848631 /* ChildSession.cpp in Sources */, BE80E45E21B6CEF200859C97 /* TemplateSectionHeaderView.m in Sources */, - BE5EB5C3213FE29900E0826C /* Session.cpp in Sources */, - BE5EB5D22140039100E0826C /* LOOLWSD.cpp in Sources */, BEFB1EE121C29CC70081D757 /* L10n.mm in Sources */, BEDCC8992456FFAD00FB02BD /* SceneDelegate.m in Sources */, BE5EB5C6213FE29900E0826C /* SigUtil.cpp in Sources */, BE5EB5C1213FE29900E0826C /* Log.cpp in Sources */, BEDCC84E2452F82800FB02BD /* MobileApp.cpp in Sources */, BE5EB5DA2140363100E0826C /* ios.mm in Sources */, - BE5EB5D421400DC100E0826C /* DocumentBroker.cpp in Sources */, - BEA28377214FFD8C00848631 /* Unit.cpp in Sources */, - BE5EB5CF213FE2D000E0826C /* ClientSession.cpp in Sources */, - BEBF3EB0246EB1C800415E87 /* RequestDetails.cpp in Sources */, BE5EB5C2213FE29900E0826C /* SpookyV2.cpp in Sources */, BE8D77402136762600AC58EA /* main.m in Sources */, - BE5EB5C8213FE29900E0826C /* FileUtil.cpp in Sources */, - BEABFC6824AC94C3004DE339 /* Authorization.cpp in Sources */, - BEA28360214ACA8500848631 /* FakeSocket.cpp in Sources */, + BE62A58724BEE1F600AFFD77 /* AppDocument.cpp in Sources */, BE80E45821B68F5700859C97 /* TemplateCollectionViewController.mm in Sources */, BE8D77352136762500AC58EA /* CODocument.mm in Sources */, BE5EB5C7213FE29900E0826C /* Protocol.cpp in Sources */, BE8D772F2136762500AC58EA /* DocumentBrowserViewController.mm in Sources */, - BE5EB5D0213FE2D000E0826C /* TileCache.cpp in Sources */, BE5EB5C5213FE29900E0826C /* MessageQueue.cpp in Sources */, + BE62A58A24BEE55200AFFD77 /* COAppDocument.mm in Sources */, BE7228E22417BC9F000ADABD /* StringVector.cpp in Sources */, - BE5EB5D621401E0F00E0826C /* Storage.cpp in Sources */, - BEA2835621467FDD00848631 /* Kit.cpp in Sources */, BE8D77322136762500AC58EA /* DocumentViewController.mm in Sources */, BE8D772C2136762500AC58EA /* AppDelegate.mm in Sources */, ); @@ -3265,8 +3211,8 @@ "-lPocoJSONd", "-lPocoNetd", ); - PRODUCT_BUNDLE_IDENTIFIER = com.collabora.office.Mobile; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = com.collabora.office.Mobile2; + PRODUCT_NAME = "Collabora Office2"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -3324,8 +3270,8 @@ "-lPocoJSONd", "-lPocoNetd", ); - PRODUCT_BUNDLE_IDENTIFIER = com.collabora.office.Mobile; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = com.collabora.office.Mobile2; + PRODUCT_NAME = "Collabora Office2"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/ios/Mobile/AppDelegate.h b/ios/Mobile/AppDelegate.h index 58c09bf463..cc6d4a6299 100644 --- a/ios/Mobile/AppDelegate.h +++ b/ios/Mobile/AppDelegate.h @@ -8,8 +8,6 @@ #import <UIKit/UIKit.h> -#import <LibreOfficeKit/LibreOfficeKit.h> - @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; diff --git a/ios/Mobile/AppDelegate.mm b/ios/Mobile/AppDelegate.mm index d6962b8404..b66c381862 100644 --- a/ios/Mobile/AppDelegate.mm +++ b/ios/Mobile/AppDelegate.mm @@ -9,14 +9,14 @@ #import "config.h" #import <cassert> -#import <cstdlib> -#import <cstring> +#import <thread> +#define LOK_USE_UNSTABLE_API #import <LibreOfficeKit/LibreOfficeKit.hxx> #define LIBO_INTERNAL_ONLY -#include <comphelper/lok.hxx> -#include <i18nlangtag/languagetag.hxx> +#import <comphelper/lok.hxx> +#import <i18nlangtag/languagetag.hxx> #import "ios.h" #import "AppDelegate.h" @@ -24,10 +24,7 @@ #import "CODocument.h" #import "DocumentViewController.h" -#import "FakeSocket.hpp" -#import "Kit.hpp" #import "Log.hpp" -#import "LOOLWSD.hpp" #import "SetupKitEnvironment.hpp" #import "Util.hpp" @@ -179,6 +176,44 @@ static void updateTemplates(NSData *data, NSURLResponse *response) } } +static int pollCallback(void* pData, int timeoutUs) +{ + std::this_thread::sleep_for(std::chrono::microseconds(timeoutUs)); + + return 0; +} + +static void wakeCallback(void* pData) +{ +} + +// We can have several documents open in the app process at the same time, thus +// several lokit_main() functions running at the same time. We want just one LO main loop, though, +// so we start it separately in its own thread. + +static void runKitLoopInAThread() +{ + std::thread([&] + { + Util::setThreadName("lokit_runloop"); + + int dummy; + lo_kit->runLoop(pollCallback, wakeCallback, &dummy); + + // Should never return + assert(false); + + NSLog(@"LOOLWSD::runLoop() unexpectedly returned"); + + std::abort(); + }).detach(); +} + +static void kitCallback(const int type, const char* p, void* data) +{ + NSLog(@"kitCallback: %s %s", lokCallbackTypeToString(type), (p ? p : "(null)")); +} + @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { @@ -201,7 +236,9 @@ static void updateTemplates(NSData *data, NSURLResponse *response) else app_locale = [[NSLocale preferredLanguages] firstObject]; - lo_kit = lok_init_2(nullptr, nullptr); + lo_kit.reset(lok::lok_cpp_init(nullptr, nullptr)); + + lo_kit->registerCallback(kitCallback, NULL); comphelper::LibreOfficeKit::setLanguageTag(LanguageTag(OUString::fromUtf8(OString([app_locale UTF8String])), true)); @@ -247,25 +284,6 @@ static void updateTemplates(NSData *data, NSURLResponse *response) } } - fakeSocketSetLoggingCallback([](const std::string& line) - { - LOG_INF_NOFILE(line); - }); - - dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^{ - char *argv[2]; - argv[0] = strdup([[NSBundle mainBundle].executablePath UTF8String]); - argv[1] = nullptr; - Util::setThreadName("app"); - auto loolwsd = new LOOLWSD(); - loolwsd->run(1, argv); - - // Should never return - assert(false); - NSLog(@"lolwsd->run() unexpectedly returned"); - std::abort(); - }); return YES; } diff --git a/ios/Mobile/COAppDocument.hpp b/ios/Mobile/COAppDocument.hpp new file mode 100644 index 0000000000..0e8ef78a51 --- /dev/null +++ b/ios/Mobile/COAppDocument.hpp @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#import "CODocument.h" +#import "AppDocument.hpp" + +class COAppDocument : public AppDocument +{ +public: + COAppDocument(std::shared_ptr<lok::Office> theLoKit, CODocument* aDocument); + + void sendMessageToJS(std::string message) override; + void sendMessageToJS(const char* buffer, int length) override; + +protected: + std::string getDocumentURL() override; + std::string getAppLocale() override; + +private: + // Objective-C pointer to the Objective-C document object. + CODocument* __weak document; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ios/Mobile/COAppDocument.mm b/ios/Mobile/COAppDocument.mm new file mode 100644 index 0000000000..93082acf64 --- /dev/null +++ b/ios/Mobile/COAppDocument.mm @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#import <string> + +#import "AppDelegate.h" +#import "CODocument.h" +#import "COAppDocument.hpp" + +COAppDocument::COAppDocument(std::shared_ptr<lok::Office> theLoKit, CODocument* aDocument) + : AppDocument(theLoKit), + document(aDocument) +{ +} + +void COAppDocument::sendMessageToJS(std::string message) +{ + [document send2JS:message]; +} + +void COAppDocument::sendMessageToJS(const char* buffer, int length) +{ + [document send2JS:buffer length:length]; +} + +std::string COAppDocument::getDocumentURL() +{ + return std::string([[document->copyFileURL absoluteString] UTF8String]); +} + +std::string COAppDocument::getAppLocale() +{ + return [app_locale UTF8String]; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ios/Mobile/CODocument.h b/ios/Mobile/CODocument.h index 7aa262c25f..638d0383d6 100644 --- a/ios/Mobile/CODocument.h +++ b/ios/Mobile/CODocument.h @@ -6,24 +6,26 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +#import <memory> #import <string> #import <UIKit/UIKit.h> -#define LOK_USE_UNSTABLE_API -#import <LibreOfficeKit/LibreOfficeKit.h> - @class DocumentViewController; +class COAppDocument; + @interface CODocument : UIDocument { @public - int fakeClientFd; NSURL *copyFileURL; - unsigned appDocId; + std::shared_ptr<COAppDocument> appDocument; } @property (weak) DocumentViewController *viewController; +- (void)handleProtocolMessage:(NSString*)message; + +- (void)send2JS:(std::string)string; - (void)send2JS:(const char*)buffer length:(int)length; @end diff --git a/ios/Mobile/CODocument.mm b/ios/Mobile/CODocument.mm index d25c7ded73..6592bc0ac4 100644 --- a/ios/Mobile/CODocument.mm +++ b/ios/Mobile/CODocument.mm @@ -8,30 +8,16 @@ #import "config.h" -#import <algorithm> +#import <cstring> -// This is not "external" code in the UNO-based extensions sense. To be able to include -// <comphelper/lok.hxx>, we must #define LIBO_INTERNAL_ONLY. - -#define LIBO_INTERNAL_ONLY #include <sal/config.h> -#include <sal/log.hxx> -#include <rtl/ustring.hxx> -#include <comphelper/lok.hxx> -#include <i18nlangtag/languagetag.hxx> #import "ios.h" #import "AppDelegate.h" +#import "COAppDocument.hpp" #import "CODocument.h" #import "DocumentViewController.h" - -#import "ClientSession.hpp" -#import "DocumentBroker.hpp" -#import "FakeSocket.hpp" -#import "Kit.hpp" -#import "KitHelper.hpp" #import "Log.hpp" -#import "LOOLWSD.hpp" #import "MobileApp.hpp" #import "Protocol.hpp" @@ -45,19 +31,11 @@ // DocBrokerId in DocumentBroker due to potential parallelism when opening multiple documents in // quick succession. -static std::atomic<unsigned> appDocIdCounter(1); - - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)errorPtr { - // If this method is called a second time on the same CODocument object, just ignore it. This - // seems to happen occasionally when the device is awakened after sleep. See tdf#122543. - if (fakeClientFd >= 0) - return YES; + appDocument = std::make_shared<COAppDocument>(lo_kit, self); - fakeClientFd = fakeSocketSocket(); - - appDocId = appDocIdCounter++; - NSURL *copyFileDirectory = [[NSFileManager.defaultManager temporaryDirectory] URLByAppendingPathComponent:[NSString stringWithFormat:@"%d", appDocId]]; + NSURL *copyFileDirectory = [[NSFileManager.defaultManager temporaryDirectory] URLByAppendingPathComponent:[NSString stringWithFormat:@"%d", appDocument->getAppDocId()]]; if (![NSFileManager.defaultManager createDirectoryAtURL:copyFileDirectory withIntermediateDirectories:YES attributes:nil error:nil]) { LOG_ERR("Could not create directory " << [[copyFileDirectory path] UTF8String]); return NO; @@ -73,12 +51,12 @@ static std::atomic<unsigned> appDocIdCounter(1); NSURL *url = [[NSBundle mainBundle] URLForResource:@"loleaflet" withExtension:@"html"]; NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; - allocateDocumentDataForMobileAppDocId(appDocId).coDocument = self; + allocateDocumentDataForMobileAppDocId(appDocument->getAppDocId()).coDocument = self; components.queryItems = @[ [NSURLQueryItem queryItemWithName:@"file_path" value:[copyFileURL absoluteString]], [NSURLQueryItem queryItemWithName:@"closebutton" value:@"1"], [NSURLQueryItem queryItemWithName:@"permission" value:@"edit"], [NSURLQueryItem queryItemWithName:@"lang" value:app_locale], - [NSURLQueryItem queryItemWithName:@"appdocid" value:[NSString stringWithFormat:@"%u", appDocId]], + [NSURLQueryItem queryItemWithName:@"appdocid" value:[NSString stringWithFormat:@"%u", appDocument->getAppDocId()]], ]; NSURLRequest *request = [[NSURLRequest alloc]initWithURL:components.URL]; @@ -87,8 +65,19 @@ static std::atomic<unsigned> appDocIdCounter(1); return YES; } +- (void)handleProtocolMessage:(NSString*)message { + const char *buffer = [message UTF8String]; + int length = strlen(buffer); + + appDocument->handleProtocolMessage(buffer, length); +} + +- (void)send2JS:(std::string)string { + [self send2JS:string.c_str() length:string.size()]; +} + - (void)send2JS:(const char *)buffer length:(int)length { - LOG_TRC("To JS: " << LOOLProtocol::getAbbreviatedMessage(buffer, length).c_str()); + LOG_ERR("To JS: " << LOOLProtocol::getAbbreviatedMessage(buffer, length).c_str()); NSString *js; @@ -114,8 +103,6 @@ static std::atomic<unsigned> appDocIdCounter(1); if (subjs.length < js.length) subjs = [subjs stringByAppendingString:@"..."]; - // LOG_TRC("Evaluating JavaScript: " << [subjs UTF8String]); - dispatch_async(dispatch_get_main_queue(), ^{ [self.viewController.webView evaluateJavaScript:js completionHandler:^(id _Nullable obj, NSError * _Nullable error) diff --git a/ios/Mobile/DocumentBrowserViewController.mm b/ios/Mobile/DocumentBrowserViewController.mm index 92a9dedf0c..6cc7001e2c 100644 --- a/ios/Mobile/DocumentBrowserViewController.mm +++ b/ios/Mobile/DocumentBrowserViewController.mm @@ -68,7 +68,6 @@ UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; DocumentViewController *documentViewController = [storyBoard instantiateViewControllerWithIdentifier:@"DocumentViewController"]; documentViewController.document = [[CODocument alloc] initWithFileURL:documentURL]; - documentViewController.document->fakeClientFd = -1; documentViewController.document.viewController = documentViewController; [self presentViewController:documentViewController animated:YES completion:nil]; } diff --git a/ios/Mobile/DocumentViewController.mm b/ios/Mobile/DocumentViewController.mm index 2467bbfbb5..660d1f05ee 100644 --- a/ios/Mobile/DocumentViewController.mm +++ b/ios/Mobile/DocumentViewController.mm @@ -15,12 +15,10 @@ #import <objc/message.h> #import <objc/runtime.h> -#import <poll.h> #import <sys/stat.h> #import "ios.h" -#import "FakeSocket.hpp" -#import "LOOLWSD.hpp" +#import "COAppDocument.hpp" #import "Log.hpp" #import "MobileApp.hpp" #import "SigUtil.hpp" @@ -180,10 +178,6 @@ static IMP standardImpOfInputAccessoryView = nil; // removed. After the photo is taken it is then added back to the hierarchy. Our Document object // is still there intact, however, so no need to re-open the document when we re-appear. - // Check whether the Document object is an already initialised one. - if (self.document->fakeClientFd >= 0) - return; - [self.document openWithCompletionHandler:^(BOOL success) { if (success) { // Display the content of the document @@ -268,9 +262,6 @@ static IMP standardImpOfInputAccessoryView = nil; } - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { - int rc; - struct pollfd p; - if ([message.name isEqualToString:@"error"]) { LOG_ERR("Error from WebView: " << [message.body UTF8String]); } else if ([message.name isEqualToString:@"debug"]) { @@ -280,82 +271,14 @@ static IMP standardImpOfInputAccessoryView = nil; if (subBody.length < ((NSString*)message.body).length) subBody = [subBody stringByAppendingString:@"..."]; - LOG_TRC("To Online: " << [subBody UTF8String]); + LOG_ERR("From JS: " << [subBody UTF8String]); if ([message.body isEqualToString:@"HULLO"]) { // Now we know that the JS has started completely - - // Contact the permanently (during app lifetime) listening LOOLWSD server - // "public" socket - assert(loolwsd_server_socket_fd != -1); - rc = fakeSocketConnect(self.document->fakeClientFd, loolwsd_server_socket_fd); - assert(rc != -1); - - // Create a socket pair to notify the below thread when the document has been closed - fakeSocketPipe2(closeNotificationPipeForForwardingThread); - - // Start another thread to read responses and forward them to the JavaScript - dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^{ - Util::setThreadName("app2js"); - while (true) { - struct pollfd p[2]; - p[0].fd = self.document->fakeClientFd; - p[0].events = POLLIN; - p[1].fd = self->closeNotificationPipeForForwardingThread[1]; - p[1].events = POLLIN; - if (fakeSocketPoll(p, 2, -1) > 0) { - if (p[1].revents == POLLIN) { - // The code below handling the "BYE" fake Websocket - // message has closed the other end of the - // closeNotificationPipeForForwardingThread. Let's close - // the other end too just for cleanliness, even if a - // FakeSocket as such is not a system resource so nothing - // is saved by closing it. - fakeSocketClose(self->closeNotificationPipeForForwardingThread[1]); - - // Close our end of the fake socket connection to the - // ClientSession thread, so that it terminates - fakeSocketClose(self.document->fakeClientFd); - - return; - } - if (p[0].revents == POLLIN) { - int n = fakeSocketAvailableDataLength(self.document->fakeClientFd); - // I don't want to check for n being -1 here, even if - // that will lead to a crash (std::length_error from the - // below std::vector constructor), as n being -1 is a - // sign of something being wrong elsewhere anyway, and I - // prefer to fix the root cause. Let's see how well this - // works out. See tdf#122543 for such a case. - if (n == 0) - return; - std::vector<char> buf(n); - n = fakeSocketRead(self.document->fakeClientFd, buf.data(), n); - [self.document send2JS:buf.data() length:n]; - } - } - else - break; - } - assert(false); - }); - - // First we simply send the Online C++ parts the URL and the appDocId. This corresponds - // to the GET request with Upgrade to WebSocket. - std::string url([[self.document->copyFileURL absoluteString] UTF8String]); - p.fd = self.document->fakeClientFd; - p.events = POLLOUT; - fakeSocketPoll(&p, 1, -1); - std::string message(url + " " + std::to_string(self.document->appDocId)); - fakeSocketWrite(self.document->fakeClientFd, message.c_str(), message.size()); - - return; } else if ([message.body isEqualToString:@"BYE"]) { LOG_TRC("Document window terminating on JavaScript side. Closing our end of the socket."); [self bye]; - return; } else if ([message.body isEqualToString:@"SLIDESHOW"]) { // Create the SVG for the slideshow. @@ -363,7 +286,7 @@ static IMP standardImpOfInputAccessoryView = nil; self.slideshowFile = Util::createRandomTmpDir() + "/slideshow.svg"; self.slideshowURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:self.slideshowFile.c_str()] isDirectory:NO]; - getDocumentDataForMobileAppDocId(self.document->appDocId).loKitDocument->saveAs([[self.slideshowURL absoluteString] UTF8String], "svg", nullptr); + getDocumentDataForMobileAppDocId(self.document->appDocument->getAppDocId()).loKitDocument->saveAs([[self.slideshowURL absoluteString] UTF8String], "svg", nullptr); // Add a new full-screen WebView displaying the slideshow. @@ -400,8 +323,6 @@ static IMP standardImpOfInputAccessoryView = nil; metrics:nil views:views]]; [self.slideshowWebView loadRequest:[NSURLRequest requestWithURL:self.slideshowURL]]; - - return; } else if ([message.body isEqualToString:@"EXITSLIDESHOW"]) { std::remove(self.slideshowFile.c_str()); @@ -409,15 +330,13 @@ static IMP standardImpOfInputAccessoryView = nil; [self.slideshowWebView removeFromSuperview]; self.slideshowWebView = nil; self.webView.hidden = false; - - return; } else if ([message.body isEqualToString:@"PRINT"]) { // Create the PDF to print. std::string printFile = Util::createRandomTmpDir() + "/print.pdf"; NSURL *printURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:printFile.c_str()] isDirectory:NO]; - getDocumentDataForMobileAppDocId(self.document->appDocId).loKitDocument->saveAs([[printURL absoluteString] UTF8String], "pdf", nullptr); + getDocumentDataForMobileAppDocId(self.document->appDocument->getAppDocId()).loKitDocument->saveAs([[printURL absoluteString] UTF8String], "pdf", nullptr); UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController]; UIPrintInfo *printInfo = [UIPrintInfo printInfo]; @@ -435,15 +354,12 @@ static IMP standardImpOfInputAccessoryView = nil; LOG_TRC("print completion handler gets " << (completed?"YES":"NO")); std::remove(printFile.c_str()); }]; - - return; } else if ([message.body hasPrefix:@"HYPERLINK"]) { NSArray *messageBodyItems = [message.body componentsSeparatedByString:@" "]; if ([messageBodyItems count] >= 2) { NSURL *url = [[NSURL alloc] initWithString:messageBodyItems[1]]; UIApplication *application = [UIApplication sharedApplication]; [application openURL:url options:@{} completionHandler:nil]; - return; } } else if ([message.body hasPrefix:@"downloadas "]) { NSArray<NSString*> *messageBodyItems = [message.body componentsSeparatedByString:@" "]; @@ -470,7 +386,7 @@ static IMP standardImpOfInputAccessoryView = nil; std::remove([[downloadAsTmpURL path] UTF8String]); - getDocumentDataForMobileAppDocId(self.document->appDocId).loKitDocument->saveAs([[downloadAsTmpURL absoluteString] UTF8String], [format UTF8String], nullptr); + getDocumentDataForMobileAppDocId(self.document->appDocument->getAppDocId()).loKitDocument->saveAs([[downloadAsTmpURL absoluteString] UTF8String], [format UTF8String], nullptr); // Then verify that it indeed was saved, and then use an // UIDocumentPickerViewController to ask the user where to store the exported @@ -499,13 +415,9 @@ static IMP standardImpOfInputAccessoryView = nil; LOG_SYS("Could not unlink tile " << [[tile path] UTF8String]); } return; + } else { + [self.document handleProtocolMessage:message.body]; } - - const char *buf = [message.body UTF8String]; - p.fd = self.document->fakeClientFd; - p.events = POLLOUT; - fakeSocketPoll(&p, 1, -1); - fakeSocketWrite(self.document->fakeClientFd, buf, strlen(buf)); } else { LOG_ERR("Unrecognized kind of message received from WebView: " << [message.name UTF8String] << ":" << [message.body UTF8String]); } @@ -526,9 +438,6 @@ static IMP standardImpOfInputAccessoryView = nil; } - (void)bye { - // Close one end of the socket pair, that will wake up the forwarding thread above - fakeSocketClose(closeNotificationPipeForForwardingThread[0]); - // deallocateDocumentDataForMobileAppDocId(self.document->appDocId); [[NSFileManager defaultManager] removeItemAtURL:self.document->copyFileURL error:nil]; diff --git a/ios/Mobile/TemplateCollectionViewController.mm b/ios/Mobile/TemplateCollectionViewController.mm index b283d580aa..9f71561252 100644 --- a/ios/Mobile/TemplateCollectionViewController.mm +++ b/ios/Mobile/TemplateCollectionViewController.mm @@ -141,9 +141,8 @@ static NSString *mapTemplateExtensionToActual(NSString *templateName) { // Load the template into LibreOffice core, save as the corresponding document type (with the // same basename), and then proceed to edit that. - LibreOfficeKitDocument *doc = lo_kit->pClass->documentLoad(lo_kit, [[selectedTemplate absoluteString] UTF8String]); - doc->pClass->saveAs(doc, [[newURL absoluteString] UTF8String], nullptr, nullptr); - doc->pClass->destroy(doc); + lok::Document *doc = lo_kit->documentLoad([[selectedTemplate absoluteString] UTF8String]); + doc->saveAs([[newURL absoluteString] UTF8String], nullptr, nullptr); self.importHandler(newURL, UIDocumentBrowserImportModeMove); @@ -7,10 +7,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <memory> + #include <LibreOfficeKit/LibreOfficeKit.hxx> extern int loolwsd_server_socket_fd; -extern LibreOfficeKit *lo_kit; +extern std::shared_ptr<lok::Office> lo_kit; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ios/ios.mm b/ios/ios.mm index b5c6ac65bd..2439287531 100644 --- a/ios/ios.mm +++ b/ios/ios.mm @@ -17,6 +17,6 @@ extern "C" { int loolwsd_server_socket_fd = -1; -LibreOfficeKit *lo_kit; +std::shared_ptr<lok::Office> lo_kit; // vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/kit/Kit.cpp b/kit/Kit.cpp index 284e552f34..bd42d5e13d 100644 --- a/kit/Kit.cpp +++ b/kit/Kit.cpp @@ -2316,33 +2316,6 @@ void lokit_main( #endif } -#ifdef IOS - -// In the iOS app we can have several documents open in the app process at the same time, thus -// several lokit_main() functions running at the same time. We want just one LO main loop, though, -// so we start it separately in its own thread. - -void runKitLoopInAThread() -{ - std::thread([&] - { - Util::setThreadName("lokit_runloop"); - - std::shared_ptr<lok::Office> loKit = std::make_shared<lok::Office>(lo_kit); - int dummy; - loKit->runLoop(pollCallback, wakeCallback, &dummy); - - // Should never return - assert(false); - - NSLog(@"loKit->runLoop() unexpectedly returned"); - - std::abort(); - }).detach(); -} - -#endif // IOS - #endif // !BUILDING_TESTS std::string anonymizeUrl(const std::string& url) diff --git a/kit/Kit.hpp b/kit/Kit.hpp index a260a9d111..1fdd376360 100644 --- a/kit/Kit.hpp +++ b/kit/Kit.hpp @@ -43,10 +43,6 @@ void lokit_main( size_t numericIdentifier ); -#ifdef IOS -void runKitLoopInAThread(); -#endif - bool globalPreinit(const std::string& loTemplate); /// Wrapper around private Document::ViewCallback(). void documentViewCallback(const int type, const char* p, void* data); |