[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.3' - 45 commits - comphelper/source desktop/inc desktop/qa desktop/source include/comphelper include/LibreOfficeKit include/sal include/sfx2 include/vcl libreofficekit/Executable_gtktiledviewer.mk libreofficekit/qa libreofficekit/README libreofficekit/source sc/qa sfx2/source sw/inc sw/source vcl/Library_vcl.mk vcl/source

Jan Holesovsky kendy at collabora.com
Wed Nov 15 20:16:20 UTC 2017


 comphelper/source/misc/lok.cxx                                      |   12 
 desktop/inc/lib/init.hxx                                            |    4 
 desktop/qa/desktop_lib/test_desktop_lib.cxx                         |   47 
 desktop/source/lib/init.cxx                                         |  296 +
 include/LibreOfficeKit/LibreOfficeKit.h                             |   63 
 include/LibreOfficeKit/LibreOfficeKit.hxx                           |  117 
 include/LibreOfficeKit/LibreOfficeKitEnums.h                        |   24 
 include/comphelper/lok.hxx                                          |    4 
 include/sal/log-areas.dox                                           |    1 
 include/sfx2/lokhelper.hxx                                          |    4 
 include/vcl/IDialogRenderable.hxx                                   |   59 
 include/vcl/ctrl.hxx                                                |    2 
 include/vcl/dialog.hxx                                              |   25 
 include/vcl/floatwin.hxx                                            |    1 
 libreofficekit/Executable_gtktiledviewer.mk                         |   27 
 libreofficekit/README                                               |    4 
 libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx                 | 2295 ----------
 libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx         |  471 ++
 libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx         |  114 
 libreofficekit/qa/gtktiledviewer/gtv-application.cxx                |  157 
 libreofficekit/qa/gtktiledviewer/gtv-application.hxx                |   42 
 libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.cxx            |  220 
 libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar.hxx            |   58 
 libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar.cxx           |  112 
 libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar.hxx           |   48 
 libreofficekit/qa/gtktiledviewer/gtv-helpers.cxx                    |  170 
 libreofficekit/qa/gtktiledviewer/gtv-helpers.hxx                    |   47 
 libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx                 |  683 ++
 libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx                 |   50 
 libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx |  408 +
 libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx |   36 
 libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.cxx               |  307 +
 libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.hxx               |   58 
 libreofficekit/qa/gtktiledviewer/gtv-main.cxx                       |   19 
 libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx            |  767 +++
 libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.hxx            |   68 
 libreofficekit/qa/gtktiledviewer/gtv.ui                             |  761 +++
 libreofficekit/source/gtk/lokdocview.cxx                            |   99 
 sc/qa/unit/screenshots/screenshots.cxx                              |    2 
 sfx2/source/dialog/basedlgs.cxx                                     |    5 
 sfx2/source/view/lokhelper.cxx                                      |   38 
 sw/inc/unotxdoc.hxx                                                 |   19 
 sw/source/uibase/uno/unotxdoc.cxx                                   |  196 
 vcl/Library_vcl.mk                                                  |    2 
 vcl/source/app/IDialogRenderable.cxx                                |   22 
 vcl/source/app/ITiledRenderable.cxx                                 |   22 
 vcl/source/control/ctrl.cxx                                         |   31 
 vcl/source/gdi/virdev.cxx                                           |   10 
 vcl/source/window/debugevent.cxx                                    |    3 
 vcl/source/window/dialog.cxx                                        |  163 
 vcl/source/window/floatwin.cxx                                      |   29 
 51 files changed, 5774 insertions(+), 2448 deletions(-)

New commits:
commit ab54d2213915ac48873e6952617cf0b23107dce3
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Thu Sep 14 09:23:46 2017 +0200

    [API CHANGE] lok: Don't use 'bool' and 'uint64_t' in the stable API.
    
    This is a f70e0ec6b3c61a7c7caa469949b0ac8016c89854 follow-up.
    
    Change-Id: I4acf00a6da85ed14be4ed0ca20d541a9441736e7
    Reviewed-on: https://gerrit.libreoffice.org/42266
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Tested-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 78688ddc4e8c..88d5201ea123 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -1286,7 +1286,7 @@ static void doc_destroy(LibreOfficeKitDocument *pThis)
 static void                    lo_destroy       (LibreOfficeKit* pThis);
 static int                     lo_initialize    (LibreOfficeKit* pThis, const char* pInstallPath, const char* pUserProfilePath);
 static LibreOfficeKitDocument* lo_documentLoad  (LibreOfficeKit* pThis, const char* pURL);
-static bool                    lo_runMacro      (LibreOfficeKit* pThis, const char* pURL);
+static int                     lo_runMacro      (LibreOfficeKit* pThis, const char* pURL);
 static char *                  lo_getError      (LibreOfficeKit* pThis);
 static void                    lo_freeError     (char* pFree);
 static LibreOfficeKitDocument* lo_documentLoadWithOptions  (LibreOfficeKit* pThis,
@@ -1296,7 +1296,7 @@ static void                    lo_registerCallback (LibreOfficeKit* pThis,
                                                     LibreOfficeKitCallback pCallback,
                                                     void* pData);
 static char* lo_getFilterTypes(LibreOfficeKit* pThis);
-static void lo_setOptionalFeatures(LibreOfficeKit* pThis, uint64_t features);
+static void                    lo_setOptionalFeatures(LibreOfficeKit* pThis, unsigned long long features);
 static void                    lo_setDocumentPassword(LibreOfficeKit* pThis,
                                                        const char* pURL,
                                                        const char* pPassword);
@@ -1465,7 +1465,7 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis,
     return nullptr;
 }
 
-static bool lo_runMacro( LibreOfficeKit* pThis, const char *pURL)
+static int lo_runMacro(LibreOfficeKit* pThis, const char *pURL)
 {
     SolarMutexGuard aGuard;
 
@@ -3367,7 +3367,7 @@ static char* lo_getFilterTypes(LibreOfficeKit* pThis)
     return strdup(aStream.str().c_str());
 }
 
-static void lo_setOptionalFeatures(LibreOfficeKit* pThis, uint64_t const features)
+static void lo_setOptionalFeatures(LibreOfficeKit* pThis, unsigned long long const features)
 {
     SolarMutexGuard aGuard;
 
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 792f5af9e4ab..7aa4ba91a8d3 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -12,10 +12,13 @@
 
 #include <stddef.h>
 
-#if defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
 // the unstable API needs C99's bool
-#include <stdbool.h>
-#include <stdint.h>
+// TODO remove the C99 types from the API before making stable
+#if defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
+# ifndef _WIN32
+#  include <stdbool.h>
+# endif
+# include <stdint.h>
 #endif
 
 #include <LibreOfficeKit/LibreOfficeKitTypes.h>
@@ -69,7 +72,7 @@ struct _LibreOfficeKitClass
     char* (*getFilterTypes) (LibreOfficeKit* pThis);
 
     /// @see lok::Office::setOptionalFeatures().
-    void (*setOptionalFeatures)(LibreOfficeKit* pThis, uint64_t features);
+    void (*setOptionalFeatures)(LibreOfficeKit* pThis, unsigned long long features);
 
     /// @see lok::Office::setDocumentPassword().
     void (*setDocumentPassword) (LibreOfficeKit* pThis,
@@ -79,7 +82,7 @@ struct _LibreOfficeKitClass
     /// @see lok::Office::getVersionInfo().
     char* (*getVersionInfo) (LibreOfficeKit* pThis);
 
-    bool (*runMacro) (LibreOfficeKit *pThis, const char* pURL);
+    int (*runMacro) (LibreOfficeKit *pThis, const char* pURL);
 #endif
 
 };
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index d595b7f2dbf5..2e4486ee4d29 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -655,7 +655,7 @@ public:
      *
      * @see LibreOfficeKitOptionalFeatures
      */
-    void setOptionalFeatures(uint64_t features)
+    void setOptionalFeatures(unsigned long long features)
     {
         return mpThis->pClass->setOptionalFeatures(mpThis, features);
     }
commit 9d72a4752128e4b59dc545018886544dc7111898
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Nov 9 14:43:46 2017 +0530

    lokdialog: Invalidate-all when size is changed
    
    Change-Id: Ic96fab62c1525154a60c0fa84e2a12ccfad15ae2

diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 0ad945815be5..9048d0e41dbe 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -160,6 +160,7 @@ public:
     bool            IsModalInputMode() const { return mbModalMode; }
 
     void            GrabFocusToFirstControl();
+    virtual void    Resize() override;
 };
 
 class VCL_DLLPUBLIC ModelessDialog : public Dialog
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index f08a22d188f9..73674200d914 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -1336,6 +1336,17 @@ void Dialog::queue_resize(StateChangedType eReason)
     SystemWindow::queue_resize(eReason);
 }
 
+void Dialog::Resize()
+{
+    SystemWindow::Resize();
+
+    // inform LOK clients
+    if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogRenderable && !maID.isEmpty())
+    {
+        mpDialogRenderable->notifyDialog(maID, "invalidate", nullptr);
+    }
+}
+
 bool Dialog::set_property(const OString &rKey, const OString &rValue)
 {
     if (rKey == "border-width")
commit 6f734170dd15272c70a3d98e5afa592015e348a1
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Wed Nov 8 19:45:13 2017 +0530

    lokdialog: Compress invalidation callbacks in Callback flush handler
    
    Change-Id: Id76bde54395611f509a5d4be6bb2ac9b7f6ed1c0
    Reviewed-on: https://gerrit.libreoffice.org/44474
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: pranavk <pranavk at collabora.co.uk>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 8603a3232faa..78688ddc4e8c 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -1043,6 +1043,139 @@ void CallbackFlushHandler::queue(const int type, const char* data)
                 }
             }
             break;
+
+            case LOK_CALLBACK_DIALOG:
+            {
+                // reading JSON by boost might be slow?
+                boost::property_tree::ptree aTree;
+                std::stringstream aStream(payload);
+                boost::property_tree::read_json(aStream, aTree);
+                const std::string aDialogId = aTree.get<std::string>("dialogId", "");
+                if (aTree.get<std::string>("action", "") == "invalidate")
+                {
+                    std::string aRectStr = aTree.get<std::string>("rectangle", "");
+                    // no 'rectangle' field => invalidate all of the dialog =>
+                    // remove all previous dialog part invalidations
+                    if (aRectStr.empty())
+                    {
+                        removeAll([&aDialogId] (const queue_type::value_type& elem) {
+                                if (elem.first == LOK_CALLBACK_DIALOG)
+                                {
+                                    boost::property_tree::ptree aOldTree;
+                                    std::stringstream aOldStream(elem.second);
+                                    boost::property_tree::read_json(aOldStream, aOldTree);
+                                    const std::string aOldDialogId = aOldTree.get<std::string>("dialogId", "");
+                                    if (aOldTree.get<std::string>("action", "") == "invalidate" &&
+                                        aDialogId == aOldDialogId)
+                                    {
+                                        return true;
+                                    }
+                                }
+                                return false;
+                            });
+                    }
+                    else
+                    {
+                        // if we have to invalidate all of the dialog, ignore
+                        // any part invalidation message
+                        const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
+                                                       [&aDialogId] (const queue_type::value_type& elem)
+                                                       {
+                                                           if (elem.first != LOK_CALLBACK_DIALOG)
+                                                               return false;
+
+                                                           boost::property_tree::ptree aOldTree;
+                                                           std::stringstream aOldStream(elem.second);
+                                                           boost::property_tree::read_json(aOldStream, aOldTree);
+                                                           const std::string aOldDialogId = aOldTree.get<std::string>("dialogId", "");
+                                                           if (aOldTree.get<std::string>("action", "") == "invalidate" &&
+                                                               aDialogId == aOldDialogId &&
+                                                               aOldTree.get<std::string>("rectangle", "").empty())
+                                                           {
+                                                               return true;
+                                                           }
+                                                           return false;
+                                                       });
+
+                        // we found a invalidate-all dialog callback
+                        if (pos != m_queue.rend())
+                        {
+                            SAL_INFO("lok.dialog", "Skipping queue [" << type << "]: [" << payload << "] since whole dialog needs to be invalidated.");
+                            return;
+                        }
+
+                        std::istringstream aRectStream(aRectStr);
+                        long nLeft, nTop, nWidth, nHeight;
+                        char nComma;
+                        aRectStream >> nLeft >> nComma >> nTop >> nComma >> nWidth >> nComma >> nHeight;
+                        Rectangle aNewRect = Rectangle(nLeft, nTop, nLeft + nWidth, nTop + nHeight);
+                        bool currentIsRedundant = false;
+                        removeAll([&aNewRect, &aDialogId, &currentIsRedundant] (const queue_type::value_type& elem) {
+                                if (elem.first != LOK_CALLBACK_DIALOG)
+                                    return false;
+
+                                boost::property_tree::ptree aOldTree;
+                                std::stringstream aOldStream(elem.second);
+                                boost::property_tree::read_json(aOldStream, aOldTree);
+                                if (aOldTree.get<std::string>("action", "") == "invalidate")
+                                {
+                                    const std::string aOldDialogId = aOldTree.get<std::string>("dialogId", "");
+                                    std::string aOldRectStr = aOldTree.get<std::string>("rectangle", "");
+                                    // not possible that we encounter an empty
+                                    // rectangle here; we already handled this
+                                    // case before
+                                    std::istringstream aOldRectStream(aOldRectStr);
+                                    long nOldLeft, nOldTop, nOldWidth, nOldHeight;
+                                    char nOldComma;
+                                    aOldRectStream >> nOldLeft >> nOldComma >> nOldTop >> nOldComma >> nOldWidth >> nOldComma >> nOldHeight;
+                                    Rectangle aOldRect = Rectangle(nOldLeft, nOldTop, nOldLeft + nOldWidth, nOldTop + nOldHeight);
+
+                                    if (aDialogId == aOldDialogId)
+                                    {
+                                        // new one engulfs the old one?
+                                        if (aNewRect.IsInside(aOldRect))
+                                        {
+                                            SAL_INFO("lok.dialog", "New " << aNewRect.toString() << " engulfs old " << aOldRect.toString() << ".");
+                                            return true;
+                                        }
+                                        // old one engulfs the new one?
+                                        else if (aOldRect.IsInside(aNewRect))
+                                        {
+                                            SAL_INFO("lok.dialog", "Old " << aOldRect.toString() << " engulfs new " << aNewRect.toString() << ".");
+                                            // we have a rectangle in the queue
+                                            // already that makes the current
+                                            // Callback useless
+                                            currentIsRedundant = true;
+                                            return false;
+                                        }
+                                        else
+                                        {
+                                            SAL_INFO("lok.dialog", "Merging " << aNewRect.toString() << " & " << aOldRect.toString());
+                                            aNewRect.Union(aOldRect);
+                                            SAL_INFO("lok.dialog", "Merged: " << aNewRect.toString());
+                                            return true;
+                                        }
+                                    }
+                                }
+
+                                // keep rest
+                                return false;
+                            });
+
+                        if (currentIsRedundant)
+                        {
+                            SAL_INFO("lok.dialog", "Current payload is engulfed by one already in the queue. Skipping redundant payload: " << aNewRect.toString());
+                            return;
+                        }
+
+                        aTree.put("rectangle", aNewRect.toString().getStr());
+                        std::stringstream aJSONStream;
+                        boost::property_tree::write_json(aJSONStream, aTree);
+                        payload = aJSONStream.str();
+                    }
+                }
+            }
+            break;
         }
     }
 
commit 3bf083c40e8fcd543a7dbbb399cb3bd3f541edd8
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Sun Nov 5 18:40:52 2017 +0530

    lokdialog: Move getting dialog information in separate LOK call
    
    Using outparameters to get the dialog information with the paintDialog
    call was quite confusing.
    
    Change-Id: Ief331b251dc66e66084b827ce5b025ba6c9ce7d2
    Reviewed-on: https://gerrit.libreoffice.org/44473
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: pranavk <pranavk at collabora.co.uk>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 55a9e18b27fa..8603a3232faa 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -631,7 +631,12 @@ static unsigned char* doc_renderFont(LibreOfficeKitDocument* pThis,
                           int* pFontHeight);
 static char* doc_getPartHash(LibreOfficeKitDocument* pThis, int nPart);
 
-static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, const int x, const int y, unsigned char* pBuffer, char** pDialogTitle, int* nWidth, int* nHeight);
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer,
+                            const int nX, const int nY,
+                            const int nWidth, const int nHeight);
+
+static void doc_getDialogInfo(LibreOfficeKitDocument* pThis, const char* pDialogId,
+                              char** pDialogTitle, int* nWidth, int* nHeight);
 
 static void doc_paintActiveFloatingWindow(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
@@ -685,6 +690,7 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
         m_pDocumentClass->getPartHash = doc_getPartHash;
 
         m_pDocumentClass->paintDialog = doc_paintDialog;
+        m_pDocumentClass->getDialogInfo = doc_getDialogInfo;
         m_pDocumentClass->paintActiveFloatingWindow = doc_paintActiveFloatingWindow;
 
         gDocumentClass = m_pDocumentClass;
@@ -3112,11 +3118,29 @@ unsigned char* doc_renderFont(LibreOfficeKitDocument* /*pThis*/,
     return nullptr;
 }
 
+static void doc_getDialogInfo(LibreOfficeKitDocument* pThis, const char* pDialogId,
+                              char** pDialogTitle, int* nWidth, int* nHeight)
+{
+    SolarMutexGuard aGuard;
+
+    IDialogRenderable* pDialogRenderable = getDialogRenderable(pThis);
+    vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
+    OUString aDialogTitle;
+    pDialogRenderable->getDialogInfo(aDialogID, aDialogTitle, *nWidth, *nHeight);
+
+    // copy dialog title
+    if (!aDialogTitle.isEmpty())
+    {
+        OString aTitleString = OUStringToOString(aDialogTitle, RTL_TEXTENCODING_UTF8);
+        *pDialogTitle = static_cast<char*>(malloc(aTitleString.getLength() + 1));
+        strcpy(*pDialogTitle, aTitleString.getStr());
+    }
+}
+
 static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId,
-                            const int x, const int y,
                             unsigned char* pBuffer,
-                            char** pDialogTitle,
-                            int* nWidth, int* nHeight)
+                            const int nX, const int nY,
+                            const int nWidth, const int nHeight)
 {
     SolarMutexGuard aGuard;
 
@@ -3125,24 +3149,16 @@ static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId
     ScopedVclPtrInstance<VirtualDevice> pDevice(nullptr, Size(1, 1), DeviceFormat::DEFAULT);
     pDevice->SetBackground(Wallpaper(Color(COL_TRANSPARENT)));
 
-    pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(*nWidth, *nHeight), Fraction(1.0), Point(), pBuffer);
+    pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nWidth, nHeight), Fraction(1.0), Point(), pBuffer);
 
     vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
 
     MapMode aMapMode(pDevice->GetMapMode());
-    aMapMode.SetOrigin(Point(-x, -y));
+    aMapMode.SetOrigin(Point(-nX, -nY));
     pDevice->SetMapMode(aMapMode);
 
     comphelper::LibreOfficeKit::setDialogPainting(true);
-    // copy the title of the dialog to outparam
-    OUString aDialogTitle;
-    pDialogRenderable->paintDialog(aDialogID, *pDevice.get(), aDialogTitle, *nWidth, *nHeight);
-    if (!aDialogTitle.isEmpty())
-    {
-        OString aTitleString = OUStringToOString(aDialogTitle, RTL_TEXTENCODING_UTF8);
-        *pDialogTitle = static_cast<char*>(malloc(aTitleString.getLength() + 1));
-        strcpy(*pDialogTitle, aTitleString.getStr());
-    }
+    pDialogRenderable->paintDialog(aDialogID, *pDevice.get());
     comphelper::LibreOfficeKit::setDialogPainting(false);
 }
 
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 3941b329a97d..792f5af9e4ab 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -255,10 +255,14 @@ struct _LibreOfficeKitDocumentClass
     /// Paints dialog with given dialog id to the buffer
     /// @see lok::Document::paintDialog().
     void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId,
-                         const int x, const int y,
                          unsigned char* pBuffer,
-                         char** pDialogTitle,
-                         int* nWidth, int* nHeight);
+                         const int x, const int y,
+                         const int width, const int height);
+
+    /// Get info about dialog with given dialog id
+    /// @see lok::Document::getDialogInfo().
+    void (*getDialogInfo) (LibreOfficeKitDocument* pThis, const char* pDialogId,
+                           char** pDialogTitle, int* pWidth, int* pHeight);
 
     /// @see lok::Document::paintActiveFloatingWindow().
     void (*paintActiveFloatingWindow) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index b029aa001ad1..d595b7f2dbf5 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -160,28 +160,38 @@ public:
      * Client must truncate pBuffer according to the nWidth and nHeight returned after the call.
      *
      * @param pDialogId Unique dialog id to be painted
+     * @param pBuffer Buffer with enough memory allocated to render any dialog
      * @param x x-coordinate from where the dialog should start painting
      * @param y y-coordinate from where the dialog should start painting
-     * @param pBuffer Buffer with enough memory allocated to render any dialog
-     * @param pDialogTitle output parameter pointing to a dialog title
-     * string. Should be freed by the caller.
-     * @param nWidth in/out parameter returning the width of the rendered
-     * dialog. The input width value is used to determined the size of the
-     * image to be painted.
-     * @param nHeight in/out parameter returning the height of the rendered
-     * dialog. The input height value is used to determine the size of the
-     * image to be painted.
+     * @param width The width of the dialog image to be painted
+     * @param height The height of the dialog image to be painted
      */
     void paintDialog(const char* pDialogId,
+                     unsigned char* pBuffer,
                      const int x,
                      const int y,
-                     unsigned char* pBuffer,
-                     char** pDialogTitle,
-                     int& nWidth,
-                     int& nHeight)
+                     const int width,
+                     const int height)
+    {
+        return mpDoc->pClass->paintDialog(mpDoc, pDialogId, pBuffer,
+                                          x, y, width, height);
+    }
+
+    /* Get info about dialog with given dialog id
+     *
+     * @param pDialogId Unique dialog id for which to get info about
+     * @param pDialogTitle Pointer to pointer pointing to string containing the
+     * dialog title. Caller should the pointer to allocated string themselves.
+     * @param pWidth The width of the dialog
+     * @param pHeight The height of the dialog
+     */
+    void getDialogInfo(const char* pDialogId,
+                       char** pDialogTitle,
+                       int& pWidth,
+                       int& pHeight)
     {
-        return mpDoc->pClass->paintDialog(mpDoc, pDialogId, x, y, pBuffer,
-                                          pDialogTitle, &nWidth, &nHeight);
+        return mpDoc->pClass->getDialogInfo(mpDoc, pDialogId, pDialogTitle, &pWidth, &pHeight);
+
     }
 
     /**
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index 94d8a1f4e9e7..357926b40446 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -30,8 +30,9 @@ class VCL_DLLPUBLIC IDialogRenderable
 public:
     virtual ~IDialogRenderable();
 
-    virtual void paintDialog(const DialogID& rDialogID, VirtualDevice &rDevice,
-                             OUString& rDialogTitle, int& nOutputWidth, int& nOutputHeight) = 0;
+    virtual void paintDialog(const DialogID& rDialogID, VirtualDevice &rDevice) = 0;
+
+    virtual void getDialogInfo(const DialogID& rDialogID, OUString& rDialogTitle, int& rWidth, int& rHeight) = 0;
 
     virtual void paintActiveFloatingWindow(const DialogID& rDialogID, VirtualDevice &rDevice,
                                            int& nOutputWidth, int& nOutputHeight) = 0;
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 2c9ae8b71003..8225d980c2c1 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -102,14 +102,16 @@ gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
     unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
     LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
     char* pDialogTitle = nullptr;
-    pDocument->pClass->paintDialog(pDocument, priv->dialogid, aRect.x, aRect.y, pBuffer, &pDialogTitle, &nWidth, &nHeight);
+    pDocument->pClass->paintDialog(pDocument, priv->dialogid, pBuffer, aRect.x, aRect.y, nWidth, nHeight);
+    int outWidth = 0, outHeight = 0;
+    pDocument->pClass->getDialogInfo(pDocument, priv->dialogid, &pDialogTitle, &outWidth, &outHeight);
     if (pDialogTitle)
     {
         gtk_window_set_title(GTK_WINDOW(pDialog), pDialogTitle);
         free(pDialogTitle);
     }
 
-    gtk_widget_set_size_request(GTK_WIDGET(pDialogDrawingArea), nWidth, nHeight);
+    gtk_widget_set_size_request(GTK_WIDGET(pDialogDrawingArea), outWidth, outHeight);
 
     cairo_surface_flush(pSurface);
     cairo_surface_mark_dirty(pSurface);
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index bb6dc4d6dbc5..00b2887e60c6 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -452,7 +452,8 @@ public:
     /// @see vcl::ITiledRenderable::getPostIts().
     OUString getPostIts() override;
 
-    void paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, OUString& rDialogTitle, int& nWidth, int& nHeight) override;
+    void paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice) override;
+    void getDialogInfo(const vcl::DialogID& rDialogID, OUString& rDialogTitle, int& rWidth, int& rHeight) override;
     void paintActiveFloatingWindow(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight) override;
     void postDialogKeyEvent(const vcl::DialogID& rDialogID, int nType,
                             int nCharCode, int nKeyCode) override;
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index ee9413b1231c..45e905646ed0 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3711,7 +3711,7 @@ void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_I
     #endif
 }
 
-void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, OUString& rDialogTitle, int& nWidth, int& nHeight)
+void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice)
 {
     SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
     SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
@@ -3737,12 +3737,27 @@ void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice&
     // register the instance so that vcl::Dialog can emit LOK callbacks
     pDlg->registerDialogRenderable(this, rDialogID);
     pDlg->paintDialog(rDevice);
+}
+
+void SwXTextDocument::getDialogInfo(const vcl::DialogID& rDialogID, OUString& rDialogTitle, int& rWidth, int& rHeight)
+{
+    SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
+    SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
+    const SfxSlot* pSlot = pSlotPool->GetUnoSlot(rDialogID);
+    if (!pSlot)
+    {
+        SAL_WARN("lok.dialog", "No slot found for " << rDialogID);
+        return;
+    }
+    SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
+    if (!pChild)
+        return;
 
-    // set outparams
+    Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
     rDialogTitle = pDlg->GetText();
     const Size aSize = pDlg->GetOptimalSize();
-    nWidth = aSize.getWidth();
-    nHeight = aSize.getHeight();
+    rWidth = aSize.getWidth();
+    rHeight = aSize.getHeight();
 }
 
 void SwXTextDocument::postDialogKeyEvent(const vcl::DialogID& rDialogID, int nType, int nCharCode, int nKeyCode)
@@ -3883,7 +3898,6 @@ void SwXTextDocument::paintActiveFloatingWindow(const vcl::DialogID& rDialogID,
         return;
 
     Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
-    // register the instance so that vcl::Dialog can emit LOK callbacks
     const Size aSize = pDlg->PaintActiveFloatingWindow(rDevice);
     nWidth = aSize.getWidth();
     nHeight = aSize.getHeight();
commit f13dfb4c018080e94d8ed247984bf2f37e0653b8
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Sun Nov 5 14:01:42 2017 +0530

    lokdialog: Support painting parts of the dialog
    
    Pass the dimensions of the region to the paintDialog call to paint only
    that much of the region in the dialog.
    
    The DIALOG_INVALIDATE callback also returns a 'rectangle' field now in
    the payload that tells the region of the dialog invalidated. It can be
    used in combination with the new paintDialog call then to paint only the
    invalidated region in the dialog.
    
    Change-Id: Iebb228865c71684e0f75dd01271b71ae41a0f906
    Reviewed-on: https://gerrit.libreoffice.org/44472
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: pranavk <pranavk at collabora.co.uk>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 6da4125ddf1d..55a9e18b27fa 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -631,7 +631,7 @@ static unsigned char* doc_renderFont(LibreOfficeKitDocument* pThis,
                           int* pFontHeight);
 static char* doc_getPartHash(LibreOfficeKitDocument* pThis, int nPart);
 
-static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, char** pDialogTitle, int* nWidth, int* nHeight);
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, const int x, const int y, unsigned char* pBuffer, char** pDialogTitle, int* nWidth, int* nHeight);
 
 static void doc_paintActiveFloatingWindow(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
@@ -3112,7 +3112,11 @@ unsigned char* doc_renderFont(LibreOfficeKitDocument* /*pThis*/,
     return nullptr;
 }
 
-static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, char** pDialogTitle, int* nWidth, int* nHeight)
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId,
+                            const int x, const int y,
+                            unsigned char* pBuffer,
+                            char** pDialogTitle,
+                            int* nWidth, int* nHeight)
 {
     SolarMutexGuard aGuard;
 
@@ -3125,8 +3129,11 @@ static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId
 
     vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
 
-    comphelper::LibreOfficeKit::setDialogPainting(true);
+    MapMode aMapMode(pDevice->GetMapMode());
+    aMapMode.SetOrigin(Point(-x, -y));
+    pDevice->SetMapMode(aMapMode);
 
+    comphelper::LibreOfficeKit::setDialogPainting(true);
     // copy the title of the dialog to outparam
     OUString aDialogTitle;
     pDialogRenderable->paintDialog(aDialogID, *pDevice.get(), aDialogTitle, *nWidth, *nHeight);
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index de425f4f965e..3941b329a97d 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -254,7 +254,11 @@ struct _LibreOfficeKitDocumentClass
 
     /// Paints dialog with given dialog id to the buffer
     /// @see lok::Document::paintDialog().
-    void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, char** pDialogTitle, int* nWidth, int* nHeight);
+    void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId,
+                         const int x, const int y,
+                         unsigned char* pBuffer,
+                         char** pDialogTitle,
+                         int* nWidth, int* nHeight);
 
     /// @see lok::Document::paintActiveFloatingWindow().
     void (*paintActiveFloatingWindow) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index 4c682cf6635a..b029aa001ad1 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -160,19 +160,27 @@ public:
      * Client must truncate pBuffer according to the nWidth and nHeight returned after the call.
      *
      * @param pDialogId Unique dialog id to be painted
+     * @param x x-coordinate from where the dialog should start painting
+     * @param y y-coordinate from where the dialog should start painting
      * @param pBuffer Buffer with enough memory allocated to render any dialog
      * @param pDialogTitle output parameter pointing to a dialog title
      * string. Should be freed by the caller.
-     * @param nWidth output parameter returning the width of the rendered dialog.
-     * @param nHeight output parameter returning the height of the rendered dialog
+     * @param nWidth in/out parameter returning the width of the rendered
+     * dialog. The input width value is used to determined the size of the
+     * image to be painted.
+     * @param nHeight in/out parameter returning the height of the rendered
+     * dialog. The input height value is used to determine the size of the
+     * image to be painted.
      */
     void paintDialog(const char* pDialogId,
+                     const int x,
+                     const int y,
                      unsigned char* pBuffer,
                      char** pDialogTitle,
                      int& nWidth,
                      int& nHeight)
     {
-        return mpDoc->pClass->paintDialog(mpDoc, pDialogId, pBuffer,
+        return mpDoc->pClass->paintDialog(mpDoc, pDialogId, x, y, pBuffer,
                                           pDialogTitle, &nWidth, &nHeight);
     }
 
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index 4738b3e65020..01d519173c2a 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -41,7 +41,7 @@ public:
     /// Same as notifyOtherViews(), but works on a selected "other" view, not on all of them.
     static void notifyOtherView(SfxViewShell* pThisView, SfxViewShell* pOtherView, int nType, const OString& rKey, const OString& rPayload);
     /// Emits a LOK_CALLBACK_DIALOG
-    static void notifyDialog(const OUString& rPayload, const OUString& rAction);
+    static void notifyDialog(const OUString& rPayload, const OUString& rAction, const Rectangle* rRect);
     /// Emits a LOK_CALLBACK_DIALOG_CHILD
     static void notifyDialogChild(const OUString& rDialogID, const OUString& rAction, const Point& rPos);
     /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index 539d2117f201..94d8a1f4e9e7 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -46,7 +46,7 @@ public:
                                            int nCount, int nButtons, int nModifier) = 0;
 
     // Callbacks
-    virtual void notifyDialog(const DialogID& rDialogID, const OUString& rAction) = 0;
+    virtual void notifyDialog(const DialogID& rDialogID, const OUString& rAction, const Rectangle* rRect) = 0;
 
     virtual void notifyDialogChild(const DialogID& rDialogID, const OUString& rAction, const Point& rPos) = 0;
 };
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-helpers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-helpers.cxx
index eb3aebf97675..5122ad2c2c02 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-helpers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-helpers.cxx
@@ -148,4 +148,23 @@ const std::string GtvHelpers::getDirPath(const std::string& filePath)
     return dirPath;
 }
 
+const std::vector<int> GtvHelpers::splitIntoIntegers(const std::string& aPayload, const std::string& aDelim, const int nItems)
+{
+    std::vector<int> aRet;
+
+    if (!aPayload.empty())
+    {
+        gchar** ppCoordinates = g_strsplit(aPayload.c_str(), aDelim.c_str(), nItems);
+        gchar** ppCoordinate  = ppCoordinates;
+        while (*ppCoordinate)
+        {
+            aRet.push_back(atoi(*ppCoordinate));
+            ++ppCoordinate;
+        }
+        g_strfreev(ppCoordinates);
+    }
+
+    return aRet;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-helpers.hxx b/libreofficekit/qa/gtktiledviewer/gtv-helpers.hxx
index 033b974f0fbd..a9c94d09a083 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-helpers.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-helpers.hxx
@@ -38,6 +38,8 @@ namespace GtvHelpers
     GtkWidget* createCommentBox(const boost::property_tree::ptree& aComment);
 
     const std::string getDirPath(const std::string& filePath);
+
+    const std::vector<int> splitIntoIntegers(const std::string& aPayload, const std::string& aDelim, const int nItems);
 }
 
 #endif
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 677245512821..2c9ae8b71003 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -87,14 +87,22 @@ gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
     GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
     GtvLokDialogPrivate* priv = getPrivate(pDialog);
 
-    g_info("panting dialog");
+    GdkRectangle aRect;
+    gdk_cairo_get_clip_rectangle(pCairo, &aRect);
+    g_info("Painting dialog region: %d, %d, %d, %d", aRect.x, aRect.y, aRect.width, aRect.height);
     int nWidth = 1024;
     int nHeight = 768;
+    if (aRect.width != 0 && aRect.height != 0)
+    {
+        nWidth = aRect.width;
+        nHeight = aRect.height;
+    }
+
     cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
     unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
     LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
     char* pDialogTitle = nullptr;
-    pDocument->pClass->paintDialog(pDocument, priv->dialogid, pBuffer, &pDialogTitle, &nWidth, &nHeight);
+    pDocument->pClass->paintDialog(pDocument, priv->dialogid, aRect.x, aRect.y, pBuffer, &pDialogTitle, &nWidth, &nHeight);
     if (pDialogTitle)
     {
         gtk_window_set_title(GTK_WINDOW(pDialog), pDialogTitle);
@@ -106,7 +114,7 @@ gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
     cairo_surface_flush(pSurface);
     cairo_surface_mark_dirty(pSurface);
 
-    cairo_set_source_surface(pCairo, pSurface, 0, 0);
+    cairo_set_source_surface(pCairo, pSurface, aRect.x, aRect.y);
     cairo_paint(pCairo);
 }
 
@@ -474,11 +482,13 @@ gtv_lok_dialog_floating_win_draw(GtkWidget* pDrawingArea, cairo_t* pCairo, gpoin
 }
 
 void
-gtv_lok_dialog_invalidate(GtvLokDialog* dialog)
+gtv_lok_dialog_invalidate(GtvLokDialog* dialog, const GdkRectangle& aRectangle)
 {
     GtvLokDialogPrivate* priv = getPrivate(dialog);
-
-    gtk_widget_queue_draw(priv->pDialogDrawingArea);
+    if (aRectangle.width != 0 && aRectangle.height != 0)
+        gtk_widget_queue_draw_area(priv->pDialogDrawingArea, aRectangle.x, aRectangle.y, aRectangle.width, aRectangle.height);
+    else
+        gtk_widget_queue_draw(priv->pDialogDrawingArea);
 }
 
 static gboolean
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
index ba565b4cebb0..619005635b60 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
@@ -37,7 +37,7 @@ GType gtv_lok_dialog_get_type               (void) G_GNUC_CONST;
 
 GtkWidget* gtv_lok_dialog_new(LOKDocView* pDocView, const gchar* dialogId);
 
-void gtv_lok_dialog_invalidate(GtvLokDialog* dialog);
+void gtv_lok_dialog_invalidate(GtvLokDialog* dialog, const GdkRectangle& aRectangle);
 
 void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY);
 
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index c177e6bf5e41..1ce1d3afbcb3 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -20,6 +20,8 @@
 #include <boost/property_tree/json_parser.hpp>
 #include <boost/optional.hpp>
 
+#include <iostream>
+
 void LOKDocViewSigHandlers::editChanged(LOKDocView* pDocView, gboolean bWasEdit, gpointer)
 {
     GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
@@ -288,8 +290,8 @@ void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpoint
     std::stringstream aStream(pPayload);
     boost::property_tree::ptree aRoot;
     boost::property_tree::read_json(aStream, aRoot);
-    std::string aDialogId = aRoot.get<std::string>("dialogId");
-    std::string aAction = aRoot.get<std::string>("action");
+    const std::string aDialogId = aRoot.get<std::string>("dialogId");
+    const std::string aAction = aRoot.get<std::string>("action");
 
     // we only understand 'invalidate' and 'close' as of now
     if (aAction != "invalidate" && aAction != "close")
@@ -306,7 +308,20 @@ void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpoint
             if (aAction == "close")
                 gtk_widget_destroy(GTK_WIDGET(pIt->data));
             else if (aAction == "invalidate")
-                gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
+            {
+                GdkRectangle aGdkRectangle = {0, 0, 0, 0};
+                try
+                {
+                    const std::string aRectangle = aRoot.get<std::string>("rectangle");
+                    std::vector<int> aRectPoints = GtvHelpers::splitIntoIntegers(aRectangle, ", ", 4);
+                    if (aRectPoints.size() == 4)
+                        aGdkRectangle = {aRectPoints[0], aRectPoints[1], aRectPoints[2], aRectPoints[3]};
+                }
+                catch(const std::exception& e)
+                {}
+
+                gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data), aGdkRectangle);
+            }
         }
         g_free(pChildDialogId);
     }
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 8128f88fef10..7e43b7ff0ce6 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -132,15 +132,18 @@ void SfxLokHelper::notifyOtherViews(SfxViewShell* pThisView, int nType, const OS
     }
 }
 
-void SfxLokHelper::notifyDialog(const OUString& rDialogID, const OUString& rAction)
+void SfxLokHelper::notifyDialog(const OUString& rDialogID, const OUString& rAction, const Rectangle* rRect)
 {
     if (SfxLokHelper::getViewsCount() <= 0 || rDialogID.isEmpty())
         return;
 
     SfxViewShell* pViewShell = SfxViewShell::GetFirst();
-    const OString aPayload = OString("{ \"dialogId\": \"") + OUStringToOString(rDialogID, RTL_TEXTENCODING_UTF8).getStr() +
-        OString("\", \"action\": \"") + OUStringToOString(rAction, RTL_TEXTENCODING_UTF8).getStr() +
-        + "\" }";
+    OString aPayload = OString("{ \"dialogId\": \"") + OUStringToOString(rDialogID, RTL_TEXTENCODING_UTF8).getStr() + OString("\"");
+    aPayload += OString(", \"action\": \"") + OUStringToOString(rAction, RTL_TEXTENCODING_UTF8).getStr() + OString("\"");
+    if (!rAction.isEmpty() && rRect && !rRect->IsEmpty())
+        aPayload += OString(", \"rectangle\": \"") + rRect->toString() + OString("\"");
+
+    aPayload += "}";
 
     while (pViewShell)
     {
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index 7719f608a287..bb6dc4d6dbc5 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -463,7 +463,7 @@ public:
     void postDialogChildMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
                                    int nCount, int nButtons, int nModifier) override;
 
-    void notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction) override;
+    void notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction, const Rectangle* rRect) override;
 
     void notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos) override;
 
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 6510af9d016e..ee9413b1231c 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3858,9 +3858,9 @@ void SwXTextDocument::postDialogChildMouseEvent(const vcl::DialogID& rDialogID,
     }
 }
 
-void SwXTextDocument::notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction)
+void SwXTextDocument::notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction, const Rectangle* rRect)
 {
-    SfxLokHelper::notifyDialog(rDialogID, rAction);
+    SfxLokHelper::notifyDialog(rDialogID, rAction, rRect);
 }
 
 void SwXTextDocument::notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos)
diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx
index 909cf170651a..b3d67d438961 100644
--- a/vcl/source/control/ctrl.cxx
+++ b/vcl/source/control/ctrl.cxx
@@ -440,8 +440,10 @@ void Control::LogicInvalidate(const Rectangle* /*pRectangle*/)
 
         // otherwise, for now, just invalidate the whole dialog
         Dialog* pParentDlg = GetParentDialog();
+
+        const Rectangle aRect(Point(GetOutOffXPixel(), GetOutOffYPixel()), Size(GetOutputWidthPixel(), GetOutputHeightPixel()));
         if (pParentDlg)
-            pParentDlg->LogicInvalidate(nullptr);
+            pParentDlg->LogicInvalidate(&aRect);
     }
 }
 
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 4ff9d42896a1..f08a22d188f9 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -596,7 +596,7 @@ void Dialog::dispose()
 
     if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable)
     {
-        mpDialogRenderable->notifyDialog(maID, "close");
+        mpDialogRenderable->notifyDialog(maID, "close", nullptr);
     }
 
     SystemWindow::dispose();
@@ -970,11 +970,11 @@ void Dialog::CloseFloatingWindow()
     }
 }
 
-void Dialog::LogicInvalidate(const Rectangle* /*pRectangle*/)
+void Dialog::LogicInvalidate(const Rectangle* pRectangle)
 {
     if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogRenderable && !maID.isEmpty())
     {
-        mpDialogRenderable->notifyDialog(maID, "invalidate");
+        mpDialogRenderable->notifyDialog(maID, "invalidate", pRectangle);
     }
 }
 
commit dd2c566b29b74d025761df77f5744c5b21e97625
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Oct 26 18:31:39 2017 -0700

    lokdialog: Tunnel dialog title to lokclient as outparam
    
    Change-Id: I1beb5ab3f06debdca7ebf999af7ac879a41ea47e
    Reviewed-on: https://gerrit.libreoffice.org/43959
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: pranavk <pranavk at collabora.co.uk>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 0e1a023b887f..6da4125ddf1d 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -631,7 +631,7 @@ static unsigned char* doc_renderFont(LibreOfficeKitDocument* pThis,
                           int* pFontHeight);
 static char* doc_getPartHash(LibreOfficeKitDocument* pThis, int nPart);
 
-static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, char** pDialogTitle, int* nWidth, int* nHeight);
 
 static void doc_paintActiveFloatingWindow(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
@@ -3112,7 +3112,7 @@ unsigned char* doc_renderFont(LibreOfficeKitDocument* /*pThis*/,
     return nullptr;
 }
 
-static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight)
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, char** pDialogTitle, int* nWidth, int* nHeight)
 {
     SolarMutexGuard aGuard;
 
@@ -3126,7 +3126,16 @@ static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId
     vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
 
     comphelper::LibreOfficeKit::setDialogPainting(true);
-    pDialogRenderable->paintDialog(aDialogID, *pDevice.get(), *nWidth, *nHeight);
+
+    // copy the title of the dialog to outparam
+    OUString aDialogTitle;
+    pDialogRenderable->paintDialog(aDialogID, *pDevice.get(), aDialogTitle, *nWidth, *nHeight);
+    if (!aDialogTitle.isEmpty())
+    {
+        OString aTitleString = OUStringToOString(aDialogTitle, RTL_TEXTENCODING_UTF8);
+        *pDialogTitle = static_cast<char*>(malloc(aTitleString.getLength() + 1));
+        strcpy(*pDialogTitle, aTitleString.getStr());
+    }
     comphelper::LibreOfficeKit::setDialogPainting(false);
 }
 
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 36d1ed7e7783..de425f4f965e 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -254,7 +254,7 @@ struct _LibreOfficeKitDocumentClass
 
     /// Paints dialog with given dialog id to the buffer
     /// @see lok::Document::paintDialog().
-    void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
+    void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, char** pDialogTitle, int* nWidth, int* nHeight);
 
     /// @see lok::Document::paintActiveFloatingWindow().
     void (*paintActiveFloatingWindow) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index ecfae8a4cad3..4c682cf6635a 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -161,16 +161,19 @@ public:
      *
      * @param pDialogId Unique dialog id to be painted
      * @param pBuffer Buffer with enough memory allocated to render any dialog
+     * @param pDialogTitle output parameter pointing to a dialog title
+     * string. Should be freed by the caller.
      * @param nWidth output parameter returning the width of the rendered dialog.
      * @param nHeight output parameter returning the height of the rendered dialog
      */
     void paintDialog(const char* pDialogId,
                      unsigned char* pBuffer,
+                     char** pDialogTitle,
                      int& nWidth,
                      int& nHeight)
     {
         return mpDoc->pClass->paintDialog(mpDoc, pDialogId, pBuffer,
-                                          &nWidth, &nHeight);
+                                          pDialogTitle, &nWidth, &nHeight);
     }
 
     /**
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index 02e959ea6fad..539d2117f201 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -31,7 +31,7 @@ public:
     virtual ~IDialogRenderable();
 
     virtual void paintDialog(const DialogID& rDialogID, VirtualDevice &rDevice,
-                             int& nOutputWidth, int& nOutputHeight) = 0;
+                             OUString& rDialogTitle, int& nOutputWidth, int& nOutputHeight) = 0;
 
     virtual void paintActiveFloatingWindow(const DialogID& rDialogID, VirtualDevice &rDevice,
                                            int& nOutputWidth, int& nOutputHeight) = 0;
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 0db80a8ef8f0..677245512821 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -87,14 +87,20 @@ gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
     GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
     GtvLokDialogPrivate* priv = getPrivate(pDialog);
 
-
     g_info("panting dialog");
     int nWidth = 1024;
     int nHeight = 768;
     cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
     unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
     LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
-    pDocument->pClass->paintDialog(pDocument, priv->dialogid, pBuffer, &nWidth, &nHeight);
+    char* pDialogTitle = nullptr;
+    pDocument->pClass->paintDialog(pDocument, priv->dialogid, pBuffer, &pDialogTitle, &nWidth, &nHeight);
+    if (pDialogTitle)
+    {
+        gtk_window_set_title(GTK_WINDOW(pDialog), pDialogTitle);
+        free(pDialogTitle);
+    }
+
     gtk_widget_set_size_request(GTK_WIDGET(pDialogDrawingArea), nWidth, nHeight);
 
     cairo_surface_flush(pSurface);
@@ -472,7 +478,6 @@ gtv_lok_dialog_invalidate(GtvLokDialog* dialog)
 {
     GtvLokDialogPrivate* priv = getPrivate(dialog);
 
-    // trigger a draw on the dialog drawing area
     gtk_widget_queue_draw(priv->pDialogDrawingArea);
 }
 
@@ -597,7 +602,7 @@ void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
     g_info("Dialog's floating window invalidate");
 
     GtvLokDialogPrivate* priv = getPrivate(dialog);
-    // remove any existing floating windows, for now
+    // create new if doesn't exist
     if (!priv->pFloatingWin)
     {
         priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index b86c570abddb..7719f608a287 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -452,7 +452,7 @@ public:
     /// @see vcl::ITiledRenderable::getPostIts().
     OUString getPostIts() override;
 
-    void paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight) override;
+    void paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, OUString& rDialogTitle, int& nWidth, int& nHeight) override;
     void paintActiveFloatingWindow(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight) override;
     void postDialogKeyEvent(const vcl::DialogID& rDialogID, int nType,
                             int nCharCode, int nKeyCode) override;
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 99921da44b47..6510af9d016e 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3711,7 +3711,7 @@ void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_I
     #endif
 }
 
-void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight)
+void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, OUString& rDialogTitle, int& nWidth, int& nHeight)
 {
     SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
     SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
@@ -3737,6 +3737,9 @@ void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice&
     // register the instance so that vcl::Dialog can emit LOK callbacks
     pDlg->registerDialogRenderable(this, rDialogID);
     pDlg->paintDialog(rDevice);
+
+    // set outparams
+    rDialogTitle = pDlg->GetText();
     const Size aSize = pDlg->GetOptimalSize();
     nWidth = aSize.getWidth();
     nHeight = aSize.getHeight();
commit 0968edb21c069c4c91836581a7c29f8e82d533bb
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Oct 26 15:25:41 2017 -0700

    lokdialog: Clear the pointer after destroying
    
    Change-Id: Iebbe3fab6f6144f0cf1de9a1c45a0b2a62b07e0b
    Reviewed-on: https://gerrit.libreoffice.org/43958
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: pranavk <pranavk at collabora.co.uk>

diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index c7f5bfe39e10..0db80a8ef8f0 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -643,7 +643,10 @@ void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
 
     GtvLokDialogPrivate* priv = getPrivate(dialog);
     if (priv->pFloatingWin)
+    {
         gtk_widget_destroy(priv->pFloatingWin);
+        priv->pFloatingWin = nullptr;
+    }
 }
 
 
commit df8f50170b502a8ad4a528507740f4f15ce1bc6d
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Oct 26 13:39:06 2017 -0700

    lokdialog: Use UNO name as dialog id when invoking lok callbacks
    
    ... not the frame id from the .ui file
    
    Remove temporary hacks introduced earlier in GTV also.
    
    Change-Id: I71290a5fac6547a5584094da21e2301ef8fbce0c
    Reviewed-on: https://gerrit.libreoffice.org/43957
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: pranavk <pranavk at collabora.co.uk>

diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 6a92883fa8e7..0ad945815be5 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -63,7 +63,8 @@ private:
 protected:
     using Window::ImplInit;
     SAL_DLLPRIVATE void    ImplInit( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag = InitFlag::Default );
-    OUString               maID; // identifier for this dialog
+    OUString               maID; // Dialog ID (UNO name) for this dialog (set
+                                 // and used by LOK for now)
 
 public:
     SAL_DLLPRIVATE bool    IsInClose() const { return mbInClose; }
@@ -74,7 +75,7 @@ public:
                    Size    PaintActiveFloatingWindow(VirtualDevice& rDevice);
 
     /// Necessary to register dialog renderable instance to emit LOK callbacks
-    void registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable);
+    void registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable, const OUString& aDialogId);
     /// Paints the current dialog to the given virtual device
     void paintDialog(VirtualDevice& rDevice);
     void LogicMouseButtonDown(const MouseEvent& rMouseEvent);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 8ad25f42a98c..c177e6bf5e41 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -288,24 +288,27 @@ void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpoint
     std::stringstream aStream(pPayload);
     boost::property_tree::ptree aRoot;
     boost::property_tree::read_json(aStream, aRoot);
-    //std::string aDialogId = aRoot.get<std::string>("dialogId");
+    std::string aDialogId = aRoot.get<std::string>("dialogId");
     std::string aAction = aRoot.get<std::string>("action");
 
     // we only understand 'invalidate' and 'close' as of now
     if (aAction != "invalidate" && aAction != "close")
         return;
 
-    // temporary hack to invalidate all open dialogs
     GList* pChildWins = gtv_application_window_get_all_child_windows(window);
     GList* pIt = nullptr;
     for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
     {
-        if (aAction == "close")
+        gchar* pChildDialogId = nullptr;
+        g_object_get(pIt->data, "dialogid", &pChildDialogId, nullptr);
+        if (g_strcmp0(pChildDialogId, aDialogId.c_str()) == 0)
         {
-            gtk_widget_destroy(GTK_WIDGET(pIt->data));
+            if (aAction == "close")
+                gtk_widget_destroy(GTK_WIDGET(pIt->data));
+            else if (aAction == "invalidate")
+                gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
         }
-        else if (aAction == "invalidate")
-            gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
+        g_free(pChildDialogId);
     }
 }
 
@@ -316,7 +319,7 @@ void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, g
     std::stringstream aStream(pPayload);
     boost::property_tree::ptree aRoot;
     boost::property_tree::read_json(aStream, aRoot);
-    //std::string aDialogId = aRoot.get<std::string>("dialogId");
+    std::string aDialogId = aRoot.get<std::string>("dialogId");
     std::string aAction = aRoot.get<std::string>("action");
     std::string aPos = aRoot.get<std::string>("position");
     gchar** ppCoordinates = g_strsplit(aPos.c_str(), ", ", 2);
@@ -332,15 +335,20 @@ void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, g
 
     g_strfreev(ppCoordinates);
 
-    // temporary hack to invalidate/close floating window of all opened dialogs
     GList* pChildWins = gtv_application_window_get_all_child_windows(window);
     GList* pIt = nullptr;
     for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
     {
-        if (aAction == "invalidate")
-            gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data), nX, nY);
-        else if (aAction == "close")
-            gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
+        gchar* pChildDialogId = nullptr;
+        g_object_get(pIt->data, "dialogid", &pChildDialogId, nullptr);
+        if (g_strcmp0(pChildDialogId, aDialogId.c_str()) == 0)
+        {
+            if (aAction == "invalidate")
+                gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data), nX, nY);
+            else if (aAction == "close")
+                gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
+        }
+        g_free(pChildDialogId);
     }
 }
 
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 7ae0e65459bd..8128f88fef10 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -134,7 +134,7 @@ void SfxLokHelper::notifyOtherViews(SfxViewShell* pThisView, int nType, const OS
 
 void SfxLokHelper::notifyDialog(const OUString& rDialogID, const OUString& rAction)
 {
-    if (SfxLokHelper::getViewsCount() <= 0)
+    if (SfxLokHelper::getViewsCount() <= 0 || rDialogID.isEmpty())
         return;
 
     SfxViewShell* pViewShell = SfxViewShell::GetFirst();
@@ -151,7 +151,7 @@ void SfxLokHelper::notifyDialog(const OUString& rDialogID, const OUString& rActi
 
 void SfxLokHelper::notifyDialogChild(const OUString& rDialogID, const OUString& rAction, const Point& rPos)
 {
-    if (SfxLokHelper::getViewsCount() <= 0)
+    if (SfxLokHelper::getViewsCount() <= 0 || rDialogID.isEmpty())
         return;
 
     SfxViewShell* pViewShell = SfxViewShell::GetFirst();
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index d29e9a593194..99921da44b47 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3735,7 +3735,7 @@ void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice&
 
     Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
     // register the instance so that vcl::Dialog can emit LOK callbacks
-    pDlg->registerDialogRenderable(this);
+    pDlg->registerDialogRenderable(this, rDialogID);
     pDlg->paintDialog(rDevice);
     const Size aSize = pDlg->GetOptimalSize();
     nWidth = aSize.getWidth();
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index a8b63bc59a72..4ff9d42896a1 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -527,7 +527,6 @@ void Dialog::doDeferredInit(WinBits nBits)
 Dialog::Dialog(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription)
     : SystemWindow(WINDOW_DIALOG)
     , mnInitFlag(InitFlag::Default)
-    , maID(rID)
 {
     ImplInitDialogData();
     loadUI(pParent, OUStringToOString(rID, RTL_TEXTENCODING_UTF8), rUIXMLDescription);
@@ -536,7 +535,6 @@ Dialog::Dialog(vcl::Window* pParent, const OUString& rID, const OUString& rUIXML
 Dialog::Dialog(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription, WindowType nType, InitFlag eFlag)
     : SystemWindow(nType)
     , mnInitFlag(eFlag)
-    , maID(rID)
 {
     ImplInitDialogData();
     loadUI(pParent, OUStringToOString(rID, RTL_TEXTENCODING_UTF8), rUIXMLDescription);
@@ -877,11 +875,12 @@ bool Dialog::selectPageByUIXMLDescription(const OString& /*rUIXMLDescription*/)
     return true;
 }
 
-void Dialog::registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable)
+void Dialog::registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable, const OUString& aDialogId)
 {
     if (pDialogRenderable && !mpDialogRenderable)
     {
         mpDialogRenderable = pDialogRenderable;
+        maID = aDialogId;
     }
 }
 
commit 1418849287f07443603feefe11c0aa51fc312c06
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Wed Oct 25 09:31:46 2017 -0700

    lokdialog: Add more dialog related methods to LOK API
    
    Change-Id: I0e4abb38e1ea9450ae9c50f71ac6e8f9150868ae

diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index bdda66709beb..ecfae8a4cad3 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -174,6 +174,25 @@ public:
     }
 
     /**
+     * Renders the active floating window of a dialog
+     *
+     * Client must truncate pBuffer according to the nWidth and nHeight returned after the call.
+     *
+     * @param pDialogId Unique dialog id
+     * @param pBuffer Buffer with enough memory allocated to render any dialog
+     * @param nWidth output parameter returning the width of the rendered dialog.
+     * @param nHeight output parameter returning the height of the rendered dialog
+     */
+    void paintActiveFloatingWindow(const char* pDialogId,
+                                   unsigned char* pBuffer,
+                                   int& nWidth,
+                                   int& nHeight)
+    {
+        return mpDoc->pClass->paintActiveFloatingWindow(mpDoc, pDialogId, pBuffer,
+                                                        &nWidth, &nHeight);
+    }
+
+    /**
      * Gets the tile mode: the pixel format used for the pBuffer of paintTile().
      *
      * @return an element of the LibreOfficeKitTileMode enum.
@@ -239,6 +258,19 @@ public:
     }
 
     /**
+     * Posts a keyboard event to the dialog
+     *
+     * @param pDialogId Dialog id on which key event should be posted
+     * @param nType Event type, like press or release.
+     * @param nCharCode contains the Unicode character generated by this event or 0
+     * @param nKeyCode contains the integer code representing the key of the event (non-zero for control keys)
+     */
+    void postDialogKeyEvent(const char* pDialogId, int nType, int nCharCode, int nKeyCode)
+    {
+        mpDoc->pClass->postDialogKeyEvent(mpDoc, pDialogId, nType, nCharCode, nKeyCode);
+    }
+
+    /**
      * Posts a mouse event to the document.
      *
      * @param nType Event type, like down, move or up.
@@ -256,7 +288,7 @@ public:
     /**
      * Posts a mouse event to the dialog with given id.
      *
-     * @param aDialogId Dialog id where mouse event is to be posted
+     * @param pDialogId Dialog id where mouse event is to be posted
      * @param nType Event type, like down, move or up.
      * @param nX horizontal position in document coordinates
      * @param nY vertical position in document coordinates
@@ -270,6 +302,23 @@ public:
     }
 
     /**
+     * Posts a mouse event to the child of a dialog with given id.
+     *
+     * @param aDialogId Dialog id
+     * @param nType Event type, like down, move or up.
+     * @param nX horizontal position in document coordinates
+     * @param nY vertical position in document coordinates
+     * @param nCount number of clicks: 1 for single click, 2 for double click
+     * @param nButtons: which mouse buttons: 1 for left, 2 for middle, 4 right
+     * @param nModifier: which keyboard modifier: (see include/vcl/vclenum.hxx for possible values)
+     */
+    void postDialogChildMouseEvent(const char* pDialogId, int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
+    {
+        mpDoc->pClass->postDialogChildMouseEvent(mpDoc, pDialogId, nType, nX, nY, nCount, nButtons, nModifier);
+    }
+
+
+    /**
      * Posts an UNO command to the document.
      *
      * Example argument string:
commit 2d6f16ec5d9eacdac82633de38402c2b5999817c
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Aug 18 15:26:26 2017 +0530

    lokdialog: Add dialog APIs to lok::Document class
    
    Change-Id: I1947dc84c91e2e01072fbff3e97aa94d514ecb5a

diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 043c42041af4..36d1ed7e7783 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -252,19 +252,21 @@ struct _LibreOfficeKitDocumentClass
                        int* pArray,
                        size_t nSize);
 
-    /// WIP
+    /// Paints dialog with given dialog id to the buffer
+    /// @see lok::Document::paintDialog().
     void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
+    /// @see lok::Document::paintActiveFloatingWindow().
     void (*paintActiveFloatingWindow) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
-    /// WIP
+    /// @see lok::Document::postDialogKeyEvent().
     void (*postDialogKeyEvent) (LibreOfficeKitDocument* pThis,
                                 const char* pDialogId,
                                 int nType,
                                 int nCharCode,
                                 int nKeyCode);
 
-    /// WIP
+    /// @see lok::Document::postDialogMouseEvent().
     void (*postDialogMouseEvent) (LibreOfficeKitDocument* pThis,
                                   const char* pDialogId,
                                   int nType,
@@ -274,7 +276,7 @@ struct _LibreOfficeKitDocumentClass
                                   int nButtons,
                                   int nModifier);
 
-        /// WIP
+    /// @see lok::Document::postDialogChildMouseEvent().
     void (*postDialogChildMouseEvent) (LibreOfficeKitDocument* pThis,
                                        const char* pDialogId,
                                        int nType,
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index b5daebbb107a..bdda66709beb 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -155,6 +155,25 @@ public:
     }
 
     /**
+     * Renders a dialog with give dialog id and writes the width and height of the rendered dialog
+     *
+     * Client must truncate pBuffer according to the nWidth and nHeight returned after the call.
+     *
+     * @param pDialogId Unique dialog id to be painted
+     * @param pBuffer Buffer with enough memory allocated to render any dialog
+     * @param nWidth output parameter returning the width of the rendered dialog.
+     * @param nHeight output parameter returning the height of the rendered dialog
+     */
+    void paintDialog(const char* pDialogId,
+                     unsigned char* pBuffer,
+                     int& nWidth,
+                     int& nHeight)
+    {
+        return mpDoc->pClass->paintDialog(mpDoc, pDialogId, pBuffer,
+                                          &nWidth, &nHeight);
+    }
+
+    /**
      * Gets the tile mode: the pixel format used for the pBuffer of paintTile().
      *
      * @return an element of the LibreOfficeKitTileMode enum.
@@ -235,6 +254,22 @@ public:
     }
 
     /**
+     * Posts a mouse event to the dialog with given id.
+     *
+     * @param aDialogId Dialog id where mouse event is to be posted
+     * @param nType Event type, like down, move or up.
+     * @param nX horizontal position in document coordinates
+     * @param nY vertical position in document coordinates
+     * @param nCount number of clicks: 1 for single click, 2 for double click
+     * @param nButtons: which mouse buttons: 1 for left, 2 for middle, 4 right
+     * @param nModifier: which keyboard modifier: (see include/vcl/vclenum.hxx for possible values)
+     */
+    void postDialogMouseEvent(const char* pDialogId, int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
+    {
+        mpDoc->pClass->postDialogMouseEvent(mpDoc, pDialogId, nType, nX, nY, nCount, nButtons, nModifier);
+    }
+
+    /**
      * Posts an UNO command to the document.
      *
      * Example argument string:
commit e2c618e5615ed8005310d5eb6d2e9218b76fd6de
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Tue Aug 15 18:54:02 2017 +0530

    lokdialog: Smoother mouse move on floating windows
    
    Do away with an early hack to create the floating window with every
    invalidate.
    
    This gets rid of persistent blinking when moving the mouse over a
    listbox, for example.
    
    Change-Id: Ida9367156605edc9835529f83529363ad97beaee

diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index b711c3bc034e..c7f5bfe39e10 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -598,34 +598,34 @@ void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
 
     GtvLokDialogPrivate* priv = getPrivate(dialog);
     // remove any existing floating windows, for now
-    if (priv->pFloatingWin)
-        gtk_widget_destroy(priv->pFloatingWin);
-
-    priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
-    GtkWidget* pDrawingArea = gtk_drawing_area_new();
-    gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);
-
-    gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
-    gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
-
-    gtk_widget_add_events(pDrawingArea,
-                          GDK_BUTTON_PRESS_MASK
-                          |GDK_POINTER_MOTION_MASK
-                          |GDK_BUTTON_RELEASE_MASK
-                          |GDK_BUTTON_MOTION_MASK);
-
-    g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
-    g_signal_connect(G_OBJECT(pDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
-    g_signal_connect(G_OBJECT(pDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
-    g_signal_connect(G_OBJECT(pDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion), dialog);
-
-    gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
-    gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
-    gtk_window_set_screen(GTK_WINDOW(priv->pFloatingWin), gtk_window_get_screen(GTK_WINDOW(dialog)));
-
-    gtk_widget_show_all(priv->pFloatingWin);
-    gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
-    gtk_widget_grab_focus(pDrawingArea);
+    if (!priv->pFloatingWin)
+    {
+        priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
+        GtkWidget* pDrawingArea = gtk_drawing_area_new();
+        gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);
+
+        gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
+        gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
+
+        gtk_widget_add_events(pDrawingArea,
+                              GDK_BUTTON_PRESS_MASK
+                              |GDK_POINTER_MOTION_MASK
+                              |GDK_BUTTON_RELEASE_MASK
+                              |GDK_BUTTON_MOTION_MASK);
+
+        g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
+        g_signal_connect(G_OBJECT(pDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
+        g_signal_connect(G_OBJECT(pDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
+        g_signal_connect(G_OBJECT(pDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion), dialog);
+
+        gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
+        gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
+        gtk_window_set_screen(GTK_WINDOW(priv->pFloatingWin), gtk_window_get_screen(GTK_WINDOW(dialog)));
+
+        gtk_widget_show_all(priv->pFloatingWin);
+        gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
+        gtk_widget_grab_focus(pDrawingArea);
+    }
 
     // Get the root coords of our new floating window
     GdkWindow* pGdkWin = gtk_widget_get_window(GTK_WIDGET(dialog));
@@ -633,6 +633,8 @@ void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
     int nrY = 0;
     gdk_window_get_root_coords(pGdkWin, nX, nY, &nrX, &nrY);
     gtk_window_move(GTK_WINDOW(priv->pFloatingWin), nrX, nrY);
+
+    gtk_widget_queue_draw(priv->pFloatingWin);
 }
 
 void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
commit 2ec9942415f8a3f9de8317d8f7beba6328733c6c
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Tue Aug 15 14:23:26 2017 +0530

    lokdialog: button press type debug info
    
    Change-Id: I193e0ab82e998905b670f7de73daae784de3ef00

diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 1149f50230b6..b711c3bc034e 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -113,7 +113,14 @@ gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
     GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
     LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
 
-    g_info("lok_dialog_signal_button: %d, %d (in twips: %d, %d)",
+    std::string aEventType = "unknown";
+    if (pEvent->type == GDK_BUTTON_PRESS)
+        aEventType = "BUTTON_PRESS";
+    else if (pEvent->type == GDK_BUTTON_RELEASE)
+        aEventType = "BUTTON_RELEASE";
+
+    g_info("lok_dialog_signal_button (type: %s): %d, %d (in twips: %d, %d)",
+           aEventType.c_str(),
            (int)pEvent->x, (int)pEvent->y,
            (int)pixelToTwip(pEvent->x),
            (int)pixelToTwip(pEvent->y));
@@ -197,7 +204,7 @@ gtv_lok_dialog_signal_motion(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
     GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
     LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
 
-    g_info("lok_dialog_signal_button: %d, %d (in twips: %d, %d)",
+    g_info("lok_dialog_signal_motion: %d, %d (in twips: %d, %d)",
            (int)pEvent->x, (int)pEvent->y,
            (int)pixelToTwip(pEvent->x),
            (int)pixelToTwip(pEvent->y));
@@ -478,7 +485,14 @@ gtv_lok_dialog_floating_win_signal_button(GtkWidget* /*pDialogChildDrawingArea*/
     GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
     LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
 
-    g_info("lok_dialog_floating_win_signal_button: %d, %d (in twips: %d, %d)",
+    std::string aEventType = "unknown";
+    if (pEvent->type == GDK_BUTTON_PRESS)
+        aEventType = "BUTTON_PRESS";
+    else if (pEvent->type == GDK_BUTTON_RELEASE)
+        aEventType = "BUTTON_RELEASE";
+
+    g_info("lok_dialog_floating_win_signal_button (type: %s): %d, %d (in twips: %d, %d)",
+           aEventType.c_str(),
            (int)pEvent->x, (int)pEvent->y,
            (int)pixelToTwip(pEvent->x),
            (int)pixelToTwip(pEvent->y));
commit ce5fef5293e8a9934ccad05e2a041d6586f8bc2e
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Aug 10 17:24:40 2017 +0530

    lokdialog: Emit dialog close callback upon dialog close
    
    Change-Id: I4ccef76cc3b2926dd8916f825671bb732e101027

diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 9fe49aaf350e..8ad25f42a98c 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -291,8 +291,8 @@ void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpoint
     //std::string aDialogId = aRoot.get<std::string>("dialogId");
     std::string aAction = aRoot.get<std::string>("action");
 
-    // we only understand 'invalidate' as of now
-    if (aAction != "invalidate")
+    // we only understand 'invalidate' and 'close' as of now
+    if (aAction != "invalidate" && aAction != "close")
         return;
 
     // temporary hack to invalidate all open dialogs
@@ -300,43 +300,48 @@ void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpoint
     GList* pIt = nullptr;
     for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
     {
-        gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
+        if (aAction == "close")
+        {
+            gtk_widget_destroy(GTK_WIDGET(pIt->data));
+        }
+        else if (aAction == "invalidate")
+            gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
     }
 }
 
 void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, gpointer)
 {
-  GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
-
-  std::stringstream aStream(pPayload);
-  boost::property_tree::ptree aRoot;
-  boost::property_tree::read_json(aStream, aRoot);
-  //std::string aDialogId = aRoot.get<std::string>("dialogId");
-  std::string aAction = aRoot.get<std::string>("action");
-  std::string aPos = aRoot.get<std::string>("position");
-  gchar** ppCoordinates = g_strsplit(aPos.c_str(), ", ", 2);
-  gchar** ppCoordinate = ppCoordinates;
-  int nX = 0;
-  int nY = 0;
-
-  if (*ppCoordinate)
-      nX = atoi(*ppCoordinate);
-  ++ppCoordinate;
-  if (*ppCoordinate)
-      nY = atoi(*ppCoordinate);
-
-  g_strfreev(ppCoordinates);
-
-  // temporary hack to invalidate/close floating window of all opened dialogs
-  GList* pChildWins = gtv_application_window_get_all_child_windows(window);
-  GList* pIt = nullptr;
-  for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
-  {
-      if (aAction == "invalidate")
-          gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data), nX, nY);
-      else if (aAction == "close")
-          gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
-  }
+    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
+
+    std::stringstream aStream(pPayload);
+    boost::property_tree::ptree aRoot;
+    boost::property_tree::read_json(aStream, aRoot);
+    //std::string aDialogId = aRoot.get<std::string>("dialogId");
+    std::string aAction = aRoot.get<std::string>("action");
+    std::string aPos = aRoot.get<std::string>("position");
+    gchar** ppCoordinates = g_strsplit(aPos.c_str(), ", ", 2);
+    gchar** ppCoordinate = ppCoordinates;
+    int nX = 0;
+    int nY = 0;
+
+    if (*ppCoordinate)
+        nX = atoi(*ppCoordinate);
+    ++ppCoordinate;
+    if (*ppCoordinate)
+        nY = atoi(*ppCoordinate);
+
+    g_strfreev(ppCoordinates);
+
+    // temporary hack to invalidate/close floating window of all opened dialogs
+    GList* pChildWins = gtv_application_window_get_all_child_windows(window);
+    GList* pIt = nullptr;
+    for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
+    {
+        if (aAction == "invalidate")
+            gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data), nX, nY);
+        else if (aAction == "close")
+            gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
+    }
 }
 
 gboolean LOKDocViewSigHandlers::configureEvent(GtkWidget* pWidget, GdkEventConfigure* /*pEvent*/, gpointer /*pData*/)
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
index 7c86b283d497..9a92d126b011 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
@@ -285,6 +285,16 @@ void changePartMode( GtkWidget* pSelector, gpointer /* pItem */ )
 static gboolean deleteLokDialog(GtkWidget* pWidget, GdkEvent* /*event*/, gpointer userdata)
 {
     GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(userdata);
+    g_info("deletLokDialog");
+    gtv_application_window_unregister_child_window(window, GTK_WINDOW(pWidget));
+
+    return FALSE;
+}
+
+static gboolean destroyLokDialog(GtkWidget* pWidget, gpointer userdata)
+{
+    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(userdata);
+    g_info("destroyLokDialog");
     gtv_application_window_unregister_child_window(window, GTK_WINDOW(pWidget));
 
     return FALSE;
@@ -296,9 +306,11 @@ void openLokDialog( GtkWidget* pSelector, gpointer /*pItem*/ )
     gchar* pDialogId = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(pSelector));
     GtkWidget* pDialog = gtv_lok_dialog_new(LOK_DOC_VIEW(window->lokdocview), pDialogId);
     gtv_application_window_register_child_window(window, GTK_WINDOW(pDialog));
+    g_signal_connect(pDialog, "destroy", G_CALLBACK(destroyLokDialog), window);
     g_signal_connect(pDialog, "delete-event", G_CALLBACK(deleteLokDialog), window);
     g_free(pDialogId);
 
+    g_info("openLokDialog");
     gtk_window_set_resizable(GTK_WINDOW(pDialog), false);
     gtk_widget_show_all(GTK_WIDGET(pDialog));
     gtk_window_present(GTK_WINDOW(pDialog));
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 149e9dd9e3b4..a8b63bc59a72 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -596,6 +596,11 @@ void Dialog::dispose()
     aObject.EventName = "DialogClosed";
     xEventBroadcaster->documentEventOccured(aObject);
 
+    if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable)
+    {
+        mpDialogRenderable->notifyDialog(maID, "close");
+    }
+
     SystemWindow::dispose();
 }
 
commit 910e8d0167886fb1144fb8fb8d5b88a948018151
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Aug 10 16:44:06 2017 +0530

    Change CB_DIALOG_INVALIDATE to CB_DIALOG
    
    We can specify whether it is an invalidation or something else in the
    payload.
    
    Change-Id: I95c5fc0a0a88b5277eaa93c8d1f9b937bddce7b3

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 8f582b639c69..0e1a023b887f 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -804,7 +804,7 @@ void CallbackFlushHandler::queue(const int type, const char* data)
         case LOK_CALLBACK_SET_PART:
         case LOK_CALLBACK_TEXT_VIEW_SELECTION:
         case LOK_CALLBACK_INVALIDATE_HEADER:
-        case LOK_CALLBACK_DIALOG_INVALIDATE:
+        case LOK_CALLBACK_DIALOG:
         {
             const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
                     [type] (const queue_type::value_type& elem) { return (elem.first == type); });
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 4c70560690da..62b9faf7ecb4 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -525,7 +525,7 @@ typedef enum
     /**
      * Dialog invalidation
      */
-    LOK_CALLBACK_DIALOG_INVALIDATE = 36,
+    LOK_CALLBACK_DIALOG = 36,
 
     /**
      * Invalidation corresponding to dialog's children.
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index ef20d03062b8..4738b3e65020 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -40,8 +40,8 @@ public:
     static void notifyOtherViews(SfxViewShell* pThisView, int nType, const OString& rKey, const OString& rPayload);
     /// Same as notifyOtherViews(), but works on a selected "other" view, not on all of them.
     static void notifyOtherView(SfxViewShell* pThisView, SfxViewShell* pOtherView, int nType, const OString& rKey, const OString& rPayload);
-    /// Emits a LOK_CALLBACK_DIALOG_INVALIDATE with 'invalidate' action
-    static void notifyDialogInvalidation(const OUString& rPayload);
+    /// Emits a LOK_CALLBACK_DIALOG
+    static void notifyDialog(const OUString& rPayload, const OUString& rAction);
     /// Emits a LOK_CALLBACK_DIALOG_CHILD
     static void notifyDialogChild(const OUString& rDialogID, const OUString& rAction, const Point& rPos);
     /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index 561f910987c6..02e959ea6fad 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -46,7 +46,7 @@ public:
                                            int nCount, int nButtons, int nModifier) = 0;
 
     // Callbacks
-    virtual void notifyDialogInvalidation(const DialogID& rDialogID) = 0;
+    virtual void notifyDialog(const DialogID& rDialogID, const OUString& rAction) = 0;
 
     virtual void notifyDialogChild(const DialogID& rDialogID, const OUString& rAction, const Point& rPos) = 0;
 };
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
index 8fbbb220f43a..dcebbe59418b 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
@@ -314,7 +314,7 @@ static void setupDocView(GtvApplicationWindow* window)
     g_signal_connect(window->lokdocview, "formula-changed", G_CALLBACK(LOKDocViewSigHandlers::formulaChanged), nullptr);
     g_signal_connect(window->lokdocview, "password-required", G_CALLBACK(LOKDocViewSigHandlers::passwordRequired), nullptr);
     g_signal_connect(window->lokdocview, "comment", G_CALLBACK(LOKDocViewSigHandlers::comment), nullptr);
-    g_signal_connect(window->lokdocview, "dialog-invalidate", G_CALLBACK(LOKDocViewSigHandlers::dialogInvalidate), nullptr);
+    g_signal_connect(window->lokdocview, "dialog", G_CALLBACK(LOKDocViewSigHandlers::dialog), nullptr);
     g_signal_connect(window->lokdocview, "dialog-child", G_CALLBACK(LOKDocViewSigHandlers::dialogChild), nullptr);
 
     g_signal_connect(window->lokdocview, "configure-event", G_CALLBACK(LOKDocViewSigHandlers::configureEvent), nullptr);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 3acd6b78e234..9fe49aaf350e 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -281,10 +281,19 @@ void LOKDocViewSigHandlers::comment(LOKDocView* pDocView, gchar* pComment, gpoin
     }
 }
 
-void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* pPayload, gpointer)
+void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpointer)
 {
     GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
-//    GtkWindow* pDialog = gtv_application_window_get_child_window_by_id(window, pDialogId);
+
+    std::stringstream aStream(pPayload);
+    boost::property_tree::ptree aRoot;
+    boost::property_tree::read_json(aStream, aRoot);
+    //std::string aDialogId = aRoot.get<std::string>("dialogId");
+    std::string aAction = aRoot.get<std::string>("action");
+
+    // we only understand 'invalidate' as of now
+    if (aAction != "invalidate")
+        return;
 
     // temporary hack to invalidate all open dialogs
     GList* pChildWins = gtv_application_window_get_all_child_windows(window);
@@ -293,11 +302,6 @@ void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* pPaylo
     {
         gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
     }
-/*  if (pDialog)
-    {
-        gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pDialog));
-    }
-*/
 }
 
 void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, gpointer)
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
index a455c3f1fc4c..54f54b396bf3 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
@@ -25,7 +25,7 @@ namespace LOKDocViewSigHandlers {
     void formulaChanged(LOKDocView* pDocView, char* pPayload, gpointer);
     void passwordRequired(LOKDocView* pDocView, char* pUrl, gboolean bModify, gpointer);
     void comment(LOKDocView* pDocView, gchar* pComment, gpointer);
-    void dialogInvalidate(LOKDocView* pDocView, gchar* pDialogId, gpointer);
+    void dialog(LOKDocView* pDocView, gchar* pDialogId, gpointer);
     void dialogChild(LOKDocView* pDocView, gchar* pPayload, gpointer);
 
     gboolean configureEvent(GtkWidget* pWidget, GdkEventConfigure* pEvent, gpointer pData);
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 5f8c007a1d7e..69644d287cde 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -279,7 +279,7 @@ enum
     PASSWORD_REQUIRED,
     COMMENT,
     RULER,
-    DIALOG_INVALIDATE,
+    DIALOG,
     DIALOG_CHILD,
 
     LAST_SIGNAL
@@ -438,8 +438,8 @@ callbackTypeToString (int nType)
         return "LOK_CALLBACK_COMMENT";
     case LOK_CALLBACK_RULER_UPDATE:
         return "LOK_CALLBACK_RULER_UPDATE";
-    case LOK_CALLBACK_DIALOG_INVALIDATE:
-        return "LOK_CALLBACK_DIALOG_INVALIDATE";
+    case LOK_CALLBACK_DIALOG:
+        return "LOK_CALLBACK_DIALOG";
     case LOK_CALLBACK_DIALOG_CHILD:
         return "LOK_CALLBACK_DIALOG_CHILD";
     }
@@ -1415,8 +1415,9 @@ callback (gpointer pData)
         break;
     case LOK_CALLBACK_RULER_UPDATE:
         g_signal_emit(pCallback->m_pDocView, doc_view_signals[RULER], 0, pCallback->m_aPayload.c_str());
-    case LOK_CALLBACK_DIALOG_INVALIDATE:
-        g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG_INVALIDATE], 0, pCallback->m_aPayload.c_str());
+        break;
+    case LOK_CALLBACK_DIALOG:
+        g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG], 0, pCallback->m_aPayload.c_str());
         break;
     case LOK_CALLBACK_DIALOG_CHILD:
         g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG_CHILD], 0, pCallback->m_aPayload.c_str());
@@ -3202,8 +3203,8 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass)
      * @pDocView: the #LOKDocView on which the signal is emitted
      * @pDialogId: The uno command for the dialog (dialog ID)
      */
-    doc_view_signals[DIALOG_INVALIDATE] =
-        g_signal_new("dialog-invalidate",
+    doc_view_signals[DIALOG] =
+        g_signal_new("dialog",
                      G_TYPE_FROM_CLASS(pGObjectClass),
                      G_SIGNAL_RUN_FIRST,
                      0,
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 6ef091c111a5..7ae0e65459bd 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -132,15 +132,19 @@ void SfxLokHelper::notifyOtherViews(SfxViewShell* pThisView, int nType, const OS
     }
 }
 
-void SfxLokHelper::notifyDialogInvalidation(const OUString& rDialogID)
+void SfxLokHelper::notifyDialog(const OUString& rDialogID, const OUString& rAction)
 {
     if (SfxLokHelper::getViewsCount() <= 0)
         return;
 
     SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+    const OString aPayload = OString("{ \"dialogId\": \"") + OUStringToOString(rDialogID, RTL_TEXTENCODING_UTF8).getStr() +
+        OString("\", \"action\": \"") + OUStringToOString(rAction, RTL_TEXTENCODING_UTF8).getStr() +
+        + "\" }";
+
     while (pViewShell)
     {
-        pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DIALOG_INVALIDATE, OUStringToOString(rDialogID, RTL_TEXTENCODING_UTF8).getStr());
+        pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DIALOG, aPayload.getStr());
         pViewShell = SfxViewShell::GetNext(*pViewShell);
     }
 }
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index f80d090273c6..b86c570abddb 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -463,7 +463,7 @@ public:
     void postDialogChildMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
                                    int nCount, int nButtons, int nModifier) override;
 
-    void notifyDialogInvalidation(const vcl::DialogID& rDialogID) override;
+    void notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction) override;
 
     void notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos) override;
 
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index c9a5358e22f4..d29e9a593194 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3855,9 +3855,9 @@ void SwXTextDocument::postDialogChildMouseEvent(const vcl::DialogID& rDialogID,
     }
 }
 
-void SwXTextDocument::notifyDialogInvalidation(const vcl::DialogID& rDialogID)
+void SwXTextDocument::notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction)
 {
-    SfxLokHelper::notifyDialogInvalidation(rDialogID);
+    SfxLokHelper::notifyDialog(rDialogID, rAction);
 }
 
 void SwXTextDocument::notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos)
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 272d18202dd8..149e9dd9e3b4 100644
--- a/vcl/source/window/dialog.cxx

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list