[Libreoffice-commits] core.git: Branch 'feature/lok_dialog' - 16 commits - comphelper/source desktop/qa desktop/source include/comphelper include/LibreOfficeKit include/sfx2 include/vcl libreofficekit/Executable_gtktiledviewer.mk libreofficekit/qa libreofficekit/source sfx2/source solenv/gdb sw/inc sw/source vcl/Library_vcl.mk vcl/source

Pranav Kant pranavk at collabora.co.uk
Sat Jul 29 07:35:54 UTC 2017


Rebased ref, commits from common ancestor:
commit 37540c4429390fa5f7d659631dc7ec3739f77766
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Sat Jul 29 11:20:34 2017 +0530

    lokdialog: Set up intial posting mouse events to dialogs
    
    Events from the dialog in GTV are forwarded correctly, but the events
    are still not processed by the dialog in core.
    
    Change-Id: Ib95ac0a3cd23f6cc2763c21425a67402b15f2de2

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index c67cc15412af..20face8e65ae 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -536,6 +536,11 @@ static void doc_postKeyEvent(LibreOfficeKitDocument* pThis,
                              int nType,
                              int nCharCode,
                              int nKeyCode);
+static void doc_postDialogKeyEvent(LibreOfficeKitDocument* pThis,
+                                   const char* pDialogId,
+                                   int nType,
+                                   int nCharCode,
+                                   int nKeyCode);
 static void doc_postMouseEvent (LibreOfficeKitDocument* pThis,
                                 int nType,
                                 int nX,
@@ -543,6 +548,14 @@ static void doc_postMouseEvent (LibreOfficeKitDocument* pThis,
                                 int nCount,
                                 int nButtons,
                                 int nModifier);
+static void doc_postDialogMouseEvent (LibreOfficeKitDocument* pThis,
+                                      const char* pDialogId,
+                                      int nType,
+                                      int nX,
+                                      int nY,
+                                      int nCount,
+                                      int nButtons,
+                                      int nModifier);
 static void doc_postUnoCommand(LibreOfficeKitDocument* pThis,
                                const char* pCommand,
                                const char* pArguments,
@@ -610,7 +623,9 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
         m_pDocumentClass->initializeForRendering = doc_initializeForRendering;
         m_pDocumentClass->registerCallback = doc_registerCallback;
         m_pDocumentClass->postKeyEvent = doc_postKeyEvent;
+        m_pDocumentClass->postDialogKeyEvent = doc_postDialogKeyEvent;
         m_pDocumentClass->postMouseEvent = doc_postMouseEvent;
+        m_pDocumentClass->postDialogMouseEvent = doc_postDialogMouseEvent;
         m_pDocumentClass->postUnoCommand = doc_postUnoCommand;
         m_pDocumentClass->setTextSelection = doc_setTextSelection;
         m_pDocumentClass->getTextSelection = doc_getTextSelection;
@@ -2065,10 +2080,24 @@ static void doc_postKeyEvent(LibreOfficeKitDocument* pThis, int nType, int nChar
         gImpl->maLastExceptionMsg = "Document doesn't support tiled rendering";
         return;
     }
-
     pDoc->postKeyEvent(nType, nCharCode, nKeyCode);
 }
 
+static void doc_postDialogKeyEvent(LibreOfficeKitDocument* pThis, const char* pDialogId, int nType, int nCharCode, int nKeyCode)
+{
+    SolarMutexGuard aGuard;
+
+    IDialogRenderable* pDoc = getDialogRenderable(pThis);
+    if (!pDoc)
+    {
+        gImpl->maLastExceptionMsg = "Document doesn't support dialog rendering";
+        return;
+    }
+
+    vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
+    pDoc->postDialogKeyEvent(aDialogID, nType, nCharCode, nKeyCode);
+}
+
 /** Class to react on finishing of a dispatched command.
 
     This will call a LOK_COMMAND_FINISHED callback when postUnoCommand was
@@ -2220,6 +2249,21 @@ static void doc_postMouseEvent(LibreOfficeKitDocument* pThis, int nType, int nX,
     }
 }
 
+static void doc_postDialogMouseEvent(LibreOfficeKitDocument* pThis, const char* pDialogId, int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
+{
+    SolarMutexGuard aGuard;
+
+    IDialogRenderable* pDoc = getDialogRenderable(pThis);
+    if (!pDoc)
+    {
+        gImpl->maLastExceptionMsg = "Document doesn't support dialog rendering";
+        return;
+    }
+
+    vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
+    pDoc->postDialogMouseEvent(aDialogID, nType, nX, nY, nCount, nButtons, nModifier);
+}
+
 static void doc_setTextSelection(LibreOfficeKitDocument* pThis, int nType, int nX, int nY)
 {
     SolarMutexGuard aGuard;
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index a37b2ecdb13d..ebb6587a373e 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -257,6 +257,23 @@ struct _LibreOfficeKitDocumentClass
     /// WIP
     void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
+    /// WIP
+    void (*postDialogKeyEvent) (LibreOfficeKitDocument* pThis,
+                                const char* pDialogId,
+                                int nType,
+                                int nCharCode,
+                                int nKeyCode);
+
+    /// WIP
+    void (*postDialogMouseEvent) (LibreOfficeKitDocument* pThis,
+                                  const char* pDialogId,
+                                  int nType,
+                                  int nX,
+                                  int nY,
+                                  int nCount,
+                                  int nButtons,
+                                  int nModifier);
+
 #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
 };
 
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index 2621ec03947a..cf9d41e54cde 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -33,11 +33,11 @@ public:
     virtual void paintDialog(const DialogID& rDialogID, VirtualDevice &rDevice,
                              int& nOutputWidth, int& nOutputHeight) = 0;
 
-    virtual void postDialogMouseEvent(const DialogID& rDialogID, int nType,
-                                      int nCharCode, int nKeyCode) = 0;
+    virtual void postDialogKeyEvent(const DialogID& rDialogID, int nType,
+                                    int nCharCode, int nKeyCode) = 0;
 
-    virtual void postDialogKeyEvent(const DialogID& rDialogID, int nType, int nX, int nY,
-                                    int nCount, int nButtons, int nModifier) = 0;
+    virtual void postDialogMouseEvent(const DialogID& rDialogID, int nType, int nX, int nY,
+                                      int nCount, int nButtons, int nModifier) = 0;
 };
 
 } // namespace vcl
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 65c71fc08c43..c9f4395cf890 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -68,8 +68,11 @@ public:
     SAL_DLLPRIVATE bool    IsInClose() const { return mbInClose; }
     virtual        void    doDeferredInit(WinBits nBits) override;
     virtual        void    LogicInvalidate(const tools::Rectangle* pRectangle) override { (void)pRectangle; }
-    // Paints the current dialog to the given virtual device
+    /// Paints the current dialog to the given virtual device
     void paintDialog(VirtualDevice& rDevice);
+    void LogicMouseButtonDown(const MouseEvent& rMouseEvent);
+    void LogicMouseButtonUp(const MouseEvent& rMouseEvent);
+    void LogicMouseButtonMove(const MouseEvent& rMouseEvent);
 
 protected:
     explicit        Dialog( WindowType nType );
diff --git a/libreofficekit/Executable_gtktiledviewer.mk b/libreofficekit/Executable_gtktiledviewer.mk
index 55434cef376e..5dd89e6065f6 100644
--- a/libreofficekit/Executable_gtktiledviewer.mk
+++ b/libreofficekit/Executable_gtktiledviewer.mk
@@ -9,10 +9,14 @@
 
 $(eval $(call gb_Executable_Executable,gtktiledviewer))
 
+$(eval $(call gb_Library_use_sdk_api,gtktiledviewer))
+
 $(eval $(call gb_Executable_set_include,gtktiledviewer,\
     $$(INCLUDE) \
     -I$(SRCDIR)/desktop/inc \
     -I$(SRCDIR)/libreofficekit/qa/gtktiledviewer/ \
+    -I$(WORKDIR)/UnoApiHeadersTarget/offapi/normal/ \
+    -I$(WORKDIR)/UnoApiHeadersTarget/udkapi/normal/ \
 ))
 
 $(eval $(call gb_Executable_use_externals,gtktiledviewer,\
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index a073198e5db3..24773ebfc9a0 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -12,11 +12,17 @@
 #include <cmath>
 #include <iostream>
 
+#include <LibreOfficeKit/LibreOfficeKitGtk.h>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
 #include <gtv-application-window.hxx>
 #include <gtv-signal-handlers.hxx>
 #include <gtv-helpers.hxx>
 #include <gtv-lok-dialog.hxx>
 
+#include <com/sun/star/awt/Key.hpp>
+#include <vcl/event.hxx>
+
 #include <map>
 #include <boost/property_tree/json_parser.hpp>
 
@@ -24,6 +30,11 @@ struct GtvLokDialogPrivate
 {
     LOKDocView* lokdocview;
     GtkWidget* pDialogDrawingArea;
+
+    guint32 m_nLastButtonPressTime;
+    guint32 m_nLastButtonReleaseTime;
+    guint32 m_nKeyModifier;
+
     gchar* dialogid;
 };
 
@@ -45,6 +56,18 @@ getPrivate(GtvLokDialog* dialog)
     return static_cast<GtvLokDialogPrivate*>(gtv_lok_dialog_get_instance_private(dialog));
 }
 
+static float
+pixelToTwip(float fInput)
+{
+    return (fInput / 96 / 1.0 /* zoom */) * 1440.0f;
+}
+
+static float
+twipToPixel(float fInput)
+{
+    return fInput / 1440.0f * 96 * 1.0 /* zoom */;
+}
+
 static void
 gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
 {
@@ -66,6 +89,89 @@ gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
     cairo_paint(pCairo);
 }
 
+static gboolean
+gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEvent)
+{
+    GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
+    GtvLokDialogPrivate* priv = getPrivate(pDialog);
+
+    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)",
+           (int)pEvent->x, (int)pEvent->y,
+           (int)pixelToTwip(pEvent->x),
+           (int)pixelToTwip(pEvent->y));
+    gtk_widget_grab_focus(GTK_WIDGET(pDialog));
+
+    switch (pEvent->type)
+    {
+    case GDK_BUTTON_PRESS:
+    {
+        int nCount = 1;
+        if ((pEvent->time - priv->m_nLastButtonPressTime) < 250)
+            nCount++;
+        priv->m_nLastButtonPressTime = pEvent->time;
+        int nEventButton = 0;
+        switch (pEvent->button)
+        {
+        case 1:
+            nEventButton = MOUSE_LEFT;
+            break;
+        case 2:
+            nEventButton = MOUSE_MIDDLE;
+            break;
+        case 3:
+            nEventButton = MOUSE_RIGHT;
+            break;
+        }
+        pDocument->pClass->postDialogMouseEvent(pDocument,
+                                                priv->dialogid,
+                                                LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+                                                pixelToTwip(pEvent->x),
+                                                pixelToTwip(pEvent->y),
+                                                nCount,
+                                                nEventButton,
+                                                0/* Modifier */);
+
+        break;
+    }
+    case GDK_BUTTON_RELEASE:
+    {
+        int nCount = 1;
+        if ((pEvent->time - priv->m_nLastButtonReleaseTime) < 250)
+            nCount++;
+        priv->m_nLastButtonReleaseTime = pEvent->time;
+        int nEventButton = 0;
+        switch (pEvent->button)
+        {
+        case 1:
+            nEventButton = MOUSE_LEFT;
+            break;
+        case 2:
+            nEventButton = MOUSE_MIDDLE;
+            break;
+        case 3:
+            nEventButton = MOUSE_RIGHT;
+            break;
+        }
+
+        pDocument->pClass->postDialogMouseEvent(pDocument,
+                                                priv->dialogid,
+                                                LOK_MOUSEEVENT_MOUSEBUTTONUP,
+                                                pixelToTwip(pEvent->x),
+                                                pixelToTwip(pEvent->y),
+                                                nCount,
+                                                nEventButton,
+                                                0/* Modifier */);
+        break;
+    }
+    default:
+        break;
+    }
+    return FALSE;
+}
+
 static void
 gtv_lok_dialog_init(GtvLokDialog* dialog)
 {
@@ -74,7 +180,17 @@ gtv_lok_dialog_init(GtvLokDialog* dialog)
     GtkWidget* pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
     priv->pDialogDrawingArea = gtk_drawing_area_new();
 
+    priv->m_nLastButtonPressTime = 0;
+    priv->m_nLastButtonReleaseTime = 0;
+    priv->m_nKeyModifier = 0;
+
+    gtk_widget_add_events(GTK_WIDGET(priv->pDialogDrawingArea),
+                          GDK_BUTTON_PRESS_MASK
+                          |GDK_BUTTON_RELEASE_MASK);
+
     g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_draw), nullptr);
+    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_signal_button), dialog);
+    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_signal_button), dialog);
     gtk_container_add(GTK_CONTAINER(pContentArea), priv->pDialogDrawingArea);
 }
 
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index ea5fdce243a0..330ead910606 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -427,11 +427,11 @@ public:
     OUString getPostIts() override;
 
     void paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight) override;
-    void postDialogMouseEvent(const vcl::DialogID& rDialogID, int nType,
-                             int nCharCode, int nKeyCode) override;
+    void postDialogKeyEvent(const vcl::DialogID& rDialogID, int nType,
+                            int nCharCode, int nKeyCode) override;
 
-    void postDialogKeyEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
-                            int nCount, int nButtons, int nModifier) override;
+    void postDialogMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
+                              int nCount, int nButtons, int nModifier) override;
 
     // css::tiledrendering::XTiledRenderable
     virtual void SAL_CALL paintTile( const ::css::uno::Any& Parent, ::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, ::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight ) override;
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 8f93d0ef8826..16de75378944 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3581,13 +3581,48 @@ void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice&
     nHeight = aSize.getHeight();
 }
 
-void SwXTextDocument::postDialogMouseEvent(const vcl::DialogID& /*rDialogID*/, int /*nType*/, int /*nCharCode*/, int /*nKeyCode*/)
+void SwXTextDocument::postDialogKeyEvent(const vcl::DialogID& /*rDialogID*/, int /*nType*/, int /*nCharCode*/, int /*nKeyCode*/)
 {
+
 }
 
-void SwXTextDocument::postDialogKeyEvent(const vcl::DialogID& /*rDialogID*/, int /*nType*/, int /*nX*/, int /*nY*/,
-                                         int /*nCount*/, int /*nButtons*/, int /*nModifier*/)
+void SwXTextDocument::postDialogMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
+                                           int nCount, int nButtons, int nModifier)
 {
+    SolarMutexGuard aGuard;
+
+    // check if dialog is already open
+    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)
+    {
+        Dialog* pDialog = static_cast<Dialog*>(pChild->GetWindow());
+        Point aPos(nX , nY);
+        MouseEvent aEvent(aPos, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier);
+
+        switch (nType)
+        {
+        case LOK_MOUSEEVENT_MOUSEBUTTONDOWN:
+            pDialog->LogicMouseButtonDown(aEvent);
+            break;
+        case LOK_MOUSEEVENT_MOUSEBUTTONUP:
+            pDialog->LogicMouseButtonUp(aEvent);
+            break;
+        case LOK_MOUSEEVENT_MOUSEMOVE:
+            //pDialog->LogicMouseMove(aEvent);
+            break;
+        default:
+            assert(false);
+            break;
+        }
+    }
 }
 
 void * SAL_CALL SwXTextDocument::operator new( size_t t) throw()
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index f341d422a1ec..de2838b681f5 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -22,6 +22,7 @@
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/util/thePathSettings.hpp>
 #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
+#include <comphelper/lok.hxx>
 #include <comphelper/processfactory.hxx>
 #include <osl/file.hxx>
 
@@ -861,6 +862,45 @@ void Dialog::paintDialog(VirtualDevice& rDevice)
     PaintToDevice(&rDevice, Point(0, 0), Size());
 }
 
+void Dialog::LogicMouseButtonDown(const MouseEvent& rMouseEvent)
+{
+    // When we're not doing tiled rendering, then positions must be passed as pixels.
+    assert(comphelper::LibreOfficeKit::isActive());
+
+    Point aPoint = GetPointerPosPixel();
+    SetLastMousePos(rMouseEvent.GetPosPixel());
+
+    MouseButtonDown(rMouseEvent);
+
+    SetPointerPosPixel(aPoint);
+}
+
+void Dialog::LogicMouseButtonUp(const MouseEvent& rMouseEvent)
+{
+    // When we're not doing tiled rendering, then positions must be passed as pixels.
+    assert(comphelper::LibreOfficeKit::isActive());
+
+    Point aPoint = GetPointerPosPixel();
+    SetLastMousePos(rMouseEvent.GetPosPixel());
+
+    MouseButtonUp(rMouseEvent);
+
+    SetPointerPosPixel(aPoint);
+}
+
+void Dialog::LogicMouseButtonMove(const MouseEvent& rMouseEvent)
+{
+    // When we're not doing tiled rendering, then positions must be passed as pixels.
+    assert(comphelper::LibreOfficeKit::isActive());
+
+    Point aPoint = GetPointerPosPixel();
+    SetLastMousePos(rMouseEvent.GetPosPixel());
+
+    MouseMove(rMouseEvent);
+
+    SetPointerPosPixel(aPoint);
+}
+
 void Dialog::ensureRepaint()
 {
     // ensure repaint
commit 78058c778a947d51d12b5aab4e2cebe670a12927
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Sat Jul 29 00:00:34 2017 +0530

    lokdialog: Suppress duplicate callbacks in flush handler
    
    Change-Id: I94578b9e9c7fc2e6a9d14effe456d821768a0bcb

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 244bfc5e8994..c67cc15412af 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -750,6 +750,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:
         {
             const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
                     [type] (const queue_type::value_type& elem) { return (elem.first == type); });
commit 0ba3634d34ca8026728ace9bcadbd2c04e12fced
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jul 28 23:59:48 2017 +0530

    lokdialog: Some checks if invalid uno command is provided
    
    Change-Id: I914564f67716f4e218d42ac4f0545e46e9609389

diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index f30028a92dff..8f93d0ef8826 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3557,6 +3557,11 @@ void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice&
     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)
     {
commit 21d874d6fc2cd15b847ef24f594804f5321bf3d6
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jul 28 23:45:25 2017 +0530

    lokdialog: Queue a redraw on invalidation in gtktiledviewer
    
    Change-Id: I081508674a71c3beb89175e4f8ac3256e6bc6c6a

diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
index fbe5746ddf1e..ab28f23578ec 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
@@ -36,6 +36,8 @@ struct GtvApplicationWindowPrivate
     gboolean toolbarBroadcast;
     gboolean partSelectorBroadcast;
 
+    GList* m_pChildWindows;
+
     // Rendering args; options with which lokdocview was rendered in this window
     GtvRenderingArgs* m_pRenderingArgs;
 };
@@ -105,6 +107,7 @@ gtv_application_window_init(GtvApplicationWindow* win)
 
     gtk_container_add(GTK_CONTAINER(win), priv->container);
 
+    priv->m_pChildWindows = nullptr;
     priv->m_pRenderingArgs = new GtvRenderingArgs();
 }
 
@@ -311,6 +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, "configure-event", G_CALLBACK(LOKDocViewSigHandlers::configureEvent), nullptr);
 }
@@ -394,6 +398,50 @@ gtv_application_window_get_part_broadcast(GtvApplicationWindow* window)
     return priv->partSelectorBroadcast;
 }
 
+void
+gtv_application_window_register_child_window(GtvApplicationWindow* window, GtkWindow* pChildWin)
+{
+    GtvApplicationWindowPrivate* priv = getPrivate(window);
+    if (pChildWin)
+        priv->m_pChildWindows = g_list_append(priv->m_pChildWindows, pChildWin);
+}
+
+void
+gtv_application_window_unregister_child_window(GtvApplicationWindow* window, GtkWindow* pChildWin)
+{
+    GtvApplicationWindowPrivate* priv = getPrivate(window);
+    if (pChildWin)
+        priv->m_pChildWindows = g_list_remove(priv->m_pChildWindows, pChildWin);
+}
+
+GtkWindow*
+gtv_application_window_get_child_window_by_id(GtvApplicationWindow* window, const gchar* pWinId)
+{
+    GtvApplicationWindowPrivate* priv = getPrivate(window);
+    GList* pIt = nullptr;
+    GtkWindow* ret = nullptr;
+    // For now, only dialogs are registered as child window
+    for (pIt = priv->m_pChildWindows; pIt != nullptr; pIt = pIt->next)
+    {
+        gchar* dialogId = nullptr;
+        g_object_get(G_OBJECT(pIt->data), "dialogid", &dialogId, nullptr);
+
+        // prepend .uno:
+        gchar* completeWinId = nullptr;
+        if (pWinId != nullptr)
+        {
+            completeWinId = g_strconcat(".uno:", pWinId, nullptr);
+        }
+
+        if (dialogId != nullptr && g_str_equal(dialogId, completeWinId))
+        {
+            ret = GTK_WINDOW(pIt->data);
+            break;
+        }
+    }
+    return ret;
+}
+
 GtvApplicationWindow*
 gtv_application_window_new(GtkApplication* app)
 {
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx
index ec3b0666d76d..c16425566967 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx
@@ -99,6 +99,12 @@ void gtv_application_window_set_part_broadcast(GtvApplicationWindow* window, boo
 
 gboolean gtv_application_window_get_part_broadcast(GtvApplicationWindow* window);
 
+void gtv_application_window_register_child_window(GtvApplicationWindow* window, GtkWindow* pChildWin);
+
+void gtv_application_window_unregister_child_window(GtvApplicationWindow* window, GtkWindow* pChildWin);
+
+GtkWindow* gtv_application_window_get_child_window_by_id(GtvApplicationWindow* window, const gchar* pWinId);
+
 G_END_DECLS
 
 #endif /* GTV_APPLICATION_WINDOW_H */
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 5b48bd1b9ed7..a073198e5db3 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -23,6 +23,7 @@
 struct GtvLokDialogPrivate
 {
     LOKDocView* lokdocview;
+    GtkWidget* pDialogDrawingArea;
     gchar* dialogid;
 };
 
@@ -68,11 +69,13 @@ gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
 static void
 gtv_lok_dialog_init(GtvLokDialog* dialog)
 {
+    GtvLokDialogPrivate* priv = getPrivate(dialog);
+
     GtkWidget* pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-    GtkWidget* pDialogDrawingArea = gtk_drawing_area_new();
+    priv->pDialogDrawingArea = gtk_drawing_area_new();
 
-    g_signal_connect(G_OBJECT(pDialogDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_draw), nullptr);
-    gtk_container_add(GTK_CONTAINER(pContentArea), pDialogDrawingArea);
+    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_draw), nullptr);
+    gtk_container_add(GTK_CONTAINER(pContentArea), priv->pDialogDrawingArea);
 }
 
 static void
@@ -150,6 +153,14 @@ gtv_lok_dialog_class_init(GtvLokDialogClass* klass)
     g_object_class_install_properties (G_OBJECT_CLASS(klass), PROP_LAST, properties);
 }
 
+void
+gtv_lok_dialog_invalidate(GtvLokDialog* dialog)
+{
+    // trigger a draw on the drawing area
+    GtvLokDialogPrivate* priv = getPrivate(dialog);
+    gtk_widget_queue_draw(priv->pDialogDrawingArea);
+}
+
 GtkWidget*
 gtv_lok_dialog_new(LOKDocView* pDocView, const gchar* dialogId)
 {
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
index 650d816e7e4a..0205f2ede3f4 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
@@ -37,6 +37,8 @@ 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);
+
 G_END_DECLS
 
 #endif /* GTV_LOK_DIALOG_H */
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 33f705262808..a549d852c786 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -15,6 +15,7 @@
 #include <gtv-calc-header-bar.hxx>
 #include <gtv-comments-sidebar.hxx>
 #include <gtv-lokdocview-signal-handlers.hxx>
+#include <gtv-lok-dialog.hxx>
 
 #include <boost/property_tree/json_parser.hpp>
 #include <boost/optional.hpp>
@@ -280,6 +281,16 @@ void LOKDocViewSigHandlers::comment(LOKDocView* pDocView, gchar* pComment, gpoin
     }
 }
 
+void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* pDialogId, 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);
+    if (pDialog)
+    {
+        gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pDialog));
+    }
+}
+
 gboolean LOKDocViewSigHandlers::configureEvent(GtkWidget* pWidget, GdkEventConfigure* /*pEvent*/, gpointer /*pData*/)
 {
     GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pWidget)));
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
index 724f2031d4f5..73bf9c2860ad 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
@@ -25,6 +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);
 
     gboolean 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 5b3b113d0a6e..7c86b283d497 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
@@ -282,11 +282,21 @@ void changePartMode( GtkWidget* pSelector, gpointer /* pItem */ )
     }
 }
 
+static gboolean deleteLokDialog(GtkWidget* pWidget, GdkEvent* /*event*/, gpointer userdata)
+{
+    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(userdata);
+    gtv_application_window_unregister_child_window(window, GTK_WINDOW(pWidget));
+
+    return FALSE;
+}
+
 void openLokDialog( GtkWidget* pSelector, gpointer /*pItem*/ )
 {
     GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(pSelector));
     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, "delete-event", G_CALLBACK(deleteLokDialog), window);
     g_free(pDialogId);
 
     gtk_window_set_resizable(GTK_WINDOW(pDialog), false);
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 142202566a96..3ee8641c6472 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -278,6 +278,7 @@ enum
     TEXT_SELECTION,
     PASSWORD_REQUIRED,
     COMMENT,
+    DIALOG_INVALIDATE,
 
     LAST_SIGNAL
 };
@@ -1425,7 +1426,7 @@ callback (gpointer pData)
         g_signal_emit(pCallback->m_pDocView, doc_view_signals[COMMENT], 0, pCallback->m_aPayload.c_str());
         break;
     case LOK_CALLBACK_DIALOG_INVALIDATE:
-        // TODO: Register the signal with lokdocview and emit it
+        g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG_INVALIDATE], 0, pCallback->m_aPayload.c_str());
         break;
     default:
         g_assert(false);
@@ -3213,6 +3214,21 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass)
                      g_cclosure_marshal_generic,
                      G_TYPE_NONE, 1,
                      G_TYPE_STRING);
+
+    /**
+     * LOKDocView::dialog-invalidate:
+     * @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",
+                     G_TYPE_FROM_CLASS(pGObjectClass),
+                     G_SIGNAL_RUN_FIRST,
+                     0,
+                     nullptr, nullptr,
+                     g_cclosure_marshal_generic,
+                     G_TYPE_NONE, 1,
+                     G_TYPE_STRING);
 }
 
 SAL_DLLPUBLIC_EXPORT GtkWidget*
commit 3825e4311ac8cdd638f1251d39aa0c34edf0e8bc
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jul 28 23:45:19 2017 +0530

    lokdialog: this is a string
    
    Change-Id: I7cb320a740cdb21da5a654cf99c887f5c7a8979d

diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 31f16ae960b5..5b48bd1b9ed7 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -106,7 +106,7 @@ gtv_lok_dialog_get_property(GObject* object, guint propId, GValue* value, GParam
         g_value_set_object(value, priv->lokdocview);
         break;
     case PROP_DIALOG_ID:
-        g_value_set_pointer(value, priv->dialogid);
+        g_value_set_string(value, priv->dialogid);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
commit 255445f68b5d6c2bc70c2864ff5ddde8fc8b8ebe
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jul 28 22:45:07 2017 +0530

    lokdialog: Set dialog painting flags while painting
    
    These are used to supress any dialog invalidations emitted while
    painting the dialog. We are not interested in any such invalidations.
    
    Change-Id: I2a7b018124af501bce18adbff0f5db85adf5fce2

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 6c99fed756ab..244bfc5e8994 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -2926,7 +2926,9 @@ 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);
+    comphelper::LibreOfficeKit::setDialogPainting(false);
 }
 
 static char* lo_getError (LibreOfficeKit *pThis)
commit 6a6928c8df5db155387820dace2f692a7b78e451
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jul 28 18:07:44 2017 +0530

    lokdialog: Dialog invalidation support
    
    For now, just invalidate the whole dialog whenever any of the controls
    in the dialog get invalidated.
    
    Since during dialog painting, many such invalidations are triggered,
    don't listen to them when we are painting.
    
    Change-Id: Ia8fc12cf9469691d60e91ef770d687e5ff01a7ef

diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx
index 44487da953ca..a4f60ac6c565 100644
--- a/comphelper/source/misc/lok.cxx
+++ b/comphelper/source/misc/lok.cxx
@@ -21,6 +21,8 @@ static bool g_bPartInInvalidation(false);
 
 static bool g_bTiledPainting(false);
 
+static bool g_bDialogPainting(false);
+
 static bool g_bTiledAnnotations(true);
 
 void setActive(bool bActive)
@@ -53,6 +55,16 @@ bool isTiledPainting()
     return g_bTiledPainting;
 }
 
+void setDialogPainting(bool bDialogPainting)
+{
+    g_bDialogPainting = bDialogPainting;
+}
+
+bool isDialogPainting()
+{
+    return g_bDialogPainting;
+}
+
 void setTiledAnnotations(bool bTiledAnnotations)
 {
     g_bTiledAnnotations = bTiledAnnotations;
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 300b71bb01ff..3905cb26ce19 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -504,7 +504,11 @@ typedef enum
     /**
      * The text content of the address field in Calc.
      */
-    LOK_CALLBACK_CELL_ADDRESS = 34
+    LOK_CALLBACK_CELL_ADDRESS = 34,
+    /**
+     * Dialog invalidation
+     */
+    LOK_CALLBACK_DIALOG_INVALIDATE = 35
 
 }
 LibreOfficeKitCallbackType;
diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx
index 253541a80cb6..7a293ca70352 100644
--- a/include/comphelper/lok.hxx
+++ b/include/comphelper/lok.hxx
@@ -52,6 +52,10 @@ COMPHELPER_DLLPUBLIC void setPartInInvalidation(bool bPartInInvalidation);
 COMPHELPER_DLLPUBLIC bool isTiledPainting();
 /// Set if we are doing tiled painting.
 COMPHELPER_DLLPUBLIC void setTiledPainting(bool bTiledPainting);
+/// Check if we are painting the dialog.
+COMPHELPER_DLLPUBLIC bool isDialogPainting();
+/// Set if we are painting the dialog.
+COMPHELPER_DLLPUBLIC void setDialogPainting(bool bDialogPainting);
 /// Set if we want no annotations rendering
 COMPHELPER_DLLPUBLIC void setTiledAnnotations(bool bTiledAnnotations);
 /// Check if annotations rendering is turned off
diff --git a/include/sfx2/basedlgs.hxx b/include/sfx2/basedlgs.hxx
index cb403c78a075..7609229db2a6 100644
--- a/include/sfx2/basedlgs.hxx
+++ b/include/sfx2/basedlgs.hxx
@@ -105,6 +105,8 @@ public:
     SfxBindings&            GetBindings()
                             { return *pBindings; }
 
+    virtual void            LogicInvalidate(const tools::Rectangle* pRectangle) override;
+
     DECL_LINK(TimerHdl, Timer *, void);
 
 };
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index 9cf98fa40c88..65cd5964af97 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -41,7 +41,9 @@ public:
     /// Same as notifyOtherViews(), but works on a selected "other" view, not on all of them.
     static void notifyOtherView(SfxViewShell* pThisView, SfxViewShell const* pOtherView, int nType, const OString& rKey, const OString& rPayload);
     /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.
-    static void notifyInvalidation(SfxViewShell const* pThisView, const OString& rPayload);
+    static void notifyDialogInvalidation(const OUString& rPayload);
+    /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.
+    static void notifyInvalidation(SfxViewShell* pThisView, const OString& rPayload);
     /// A special value to signify 'infinity'.
     /// This value is chosen such that sal_Int32 will not overflow when manipulated.
     static const long MaxTwips = 1e9;
diff --git a/include/vcl/ctrl.hxx b/include/vcl/ctrl.hxx
index cb68cfe8f78a..8e2926ae1774 100644
--- a/include/vcl/ctrl.hxx
+++ b/include/vcl/ctrl.hxx
@@ -44,6 +44,8 @@ private:
 
     SAL_DLLPRIVATE void     ImplInitControlData();
 
+    virtual void            LogicInvalidate(const tools::Rectangle* pRectangle) override;
+
                             Control (const Control &) = delete;
                             Control & operator= (const Control &) = delete;
 
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index e452b9f50f48..65c71fc08c43 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -62,10 +62,14 @@ private:
 protected:
     using Window::ImplInit;
     SAL_DLLPRIVATE void    ImplInit( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag = InitFlag::Default );
+    OUString               maID; // identifier for this dialog
 
 public:
     SAL_DLLPRIVATE bool    IsInClose() const { return mbInClose; }
     virtual        void    doDeferredInit(WinBits nBits) override;
+    virtual        void    LogicInvalidate(const tools::Rectangle* pRectangle) override { (void)pRectangle; }
+    // Paints the current dialog to the given virtual device
+    void paintDialog(VirtualDevice& rDevice);
 
 protected:
     explicit        Dialog( WindowType nType );
@@ -101,9 +105,6 @@ public:
     virtual void PrePaint(vcl::RenderContext& rRenderContext) override;
     virtual void PostPaint(vcl::RenderContext& rRenderContext) override;
 
-    // Paints the current dialog to the given virtual device
-    void paintDialog(VirtualDevice& rDevice);
-
     // ensureRepaint - triggers Application::Yield until the dialog is
     // completely repainted. Sometimes needed for dialogs showing progress
     // during actions
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 88cf455e728c..142202566a96 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -433,6 +433,8 @@ callbackTypeToString (int nType)
         return "LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED";
     case LOK_CALLBACK_COMMENT:
         return "LOK_CALLBACK_COMMENT";
+    case LOK_CALLBACK_DIALOG_INVALIDATE:
+        return "LOK_CALLBACK_DIALOG_INVALIDATE";
     }
     g_assert(false);
     return nullptr;
@@ -1422,6 +1424,9 @@ callback (gpointer pData)
     case LOK_CALLBACK_COMMENT:
         g_signal_emit(pCallback->m_pDocView, doc_view_signals[COMMENT], 0, pCallback->m_aPayload.c_str());
         break;
+    case LOK_CALLBACK_DIALOG_INVALIDATE:
+        // TODO: Register the signal with lokdocview and emit it
+        break;
     default:
         g_assert(false);
         break;
diff --git a/sfx2/source/dialog/basedlgs.cxx b/sfx2/source/dialog/basedlgs.cxx
index 30a14417d389..d140c571ab62 100644
--- a/sfx2/source/dialog/basedlgs.cxx
+++ b/sfx2/source/dialog/basedlgs.cxx
@@ -18,7 +18,10 @@
  */
 
 #include <stdlib.h>
+
+#include <comphelper/lok.hxx>
 #include <comphelper/processfactory.hxx>
+
 #include <osl/file.hxx>
 #include <vcl/fixed.hxx>
 #include <vcl/help.hxx>
@@ -29,6 +32,7 @@
 #include <vcl/idle.hxx>
 
 #include <sfx2/basedlgs.hxx>
+#include <sfx2/lokhelper.hxx>
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/tabdlg.hxx>
 #include <sfx2/app.hxx>
@@ -390,6 +394,13 @@ void SfxModelessDialog::FillInfo(SfxChildWinInfo& rInfo) const
 }
 
 
+void SfxModelessDialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+{
+    if (!comphelper::LibreOfficeKit::isDialogPainting())
+        SfxLokHelper::notifyDialogInvalidation(maID);
+}
+
+
 bool SfxFloatingWindow::EventNotify( NotifyEvent& rEvt )
 
 /*  [Description]
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 1597174af5b0..46d736206ddf 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -144,7 +144,20 @@ void SfxLokHelper::notifyOtherViews(SfxViewShell* pThisView, int nType, const OS
     }
 }
 
-void SfxLokHelper::notifyInvalidation(SfxViewShell const* pThisView, const OString& rPayload)
+void SfxLokHelper::notifyDialogInvalidation(const OUString& rDialogID)
+{
+    if (SfxLokHelper::getViewsCount() <= 0)
+        return;
+
+    SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+    while (pViewShell)
+    {
+        pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DIALOG_INVALIDATE, OUStringToOString(rDialogID, RTL_TEXTENCODING_UTF8).getStr());
+        pViewShell = SfxViewShell::GetNext(*pViewShell);
+    }
+}
+
+void SfxLokHelper::notifyInvalidation(SfxViewShell* pThisView, const OString& rPayload)
 {
     OStringBuffer aBuf;
     aBuf.append(rPayload);
diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx
index 5df29a0d3560..3bd877ea7162 100644
--- a/vcl/source/control/ctrl.cxx
+++ b/vcl/source/control/ctrl.cxx
@@ -18,11 +18,13 @@
  */
 
 #include <comphelper/processfactory.hxx>
+#include <comphelper/lok.hxx>
 
 #include <vcl/svapp.hxx>
 #include <vcl/event.hxx>
 #include <vcl/ctrl.hxx>
 #include <vcl/decoview.hxx>
+#include <vcl/dialog.hxx>
 #include <vcl/salnativewidgets.hxx>
 #include <vcl/settings.hxx>
 #include <vcl/uitest/logger.hxx>
@@ -412,6 +414,19 @@ void Control::ImplInitSettings()
     ApplySettings(*this);
 }
 
+void Control::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+{
+    // Several repaint, resize invalidations are emitted when we are painting,
+    // ignore all of those
+    if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isDialogPainting())
+    {
+        // For now just invalidate the whole dialog
+        Dialog* pParentDlg = GetParentDialog();
+        if (pParentDlg)
+            pParentDlg->LogicInvalidate(nullptr);
+    }
+}
+
 tools::Rectangle Control::DrawControlText( OutputDevice& _rTargetDevice, const tools::Rectangle& rRect, const OUString& _rStr,
     DrawTextFlags _nStyle, MetricVector* _pVector, OUString* _pDisplayText, const Size* i_pDeviceSize ) const
 {
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 58f7d505b6ba..f341d422a1ec 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -505,6 +505,7 @@ void Dialog::doDeferredInit(WinBits nBits)
 Dialog::Dialog(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription)
     : SystemWindow(WindowType::DIALOG)
     , mnInitFlag(InitFlag::Default)
+    , maID(rID)
 {
     ImplInitDialogData();
     loadUI(pParent, OUStringToOString(rID, RTL_TEXTENCODING_UTF8), rUIXMLDescription);
@@ -513,6 +514,7 @@ 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);
commit 71c7555773176006d7d6b594cc5e872329600005
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jul 14 18:54:52 2017 +0530

    gtktiledviewer: Implement modeless dialog rendering
    
    Hardcode modeless dialogs available in writer (very few) as of now in
    the combobox.
    
    Change-Id: I82d1442fbc71776dd64640ad048a0375ca041a67

diff --git a/libreofficekit/Executable_gtktiledviewer.mk b/libreofficekit/Executable_gtktiledviewer.mk
index f0667e247680..55434cef376e 100644
--- a/libreofficekit/Executable_gtktiledviewer.mk
+++ b/libreofficekit/Executable_gtktiledviewer.mk
@@ -53,6 +53,7 @@ $(eval $(call gb_Executable_add_exception_objects,gtktiledviewer,\
     libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers \
     libreofficekit/qa/gtktiledviewer/gtv-calc-header-bar \
     libreofficekit/qa/gtktiledviewer/gtv-comments-sidebar \
+    libreofficekit/qa/gtktiledviewer/gtv-lok-dialog \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
index dae6821600e7..fbe5746ddf1e 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
@@ -31,6 +31,7 @@ struct GtvApplicationWindowPrivate
     GtkWidget* gridcontainer;
     GtkWidget* toolbarcontainer;
     GtkWidget* scrolledwindowcontainer;
+    GtkWidget* lokDialog;
 
     gboolean toolbarBroadcast;
     gboolean partSelectorBroadcast;
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
new file mode 100644
index 000000000000..31f16ae960b5
--- /dev/null
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <gtk/gtk.h>
+
+#include <cmath>
+#include <iostream>
+
+#include <gtv-application-window.hxx>
+#include <gtv-signal-handlers.hxx>
+#include <gtv-helpers.hxx>
+#include <gtv-lok-dialog.hxx>
+
+#include <map>
+#include <boost/property_tree/json_parser.hpp>
+
+struct GtvLokDialogPrivate
+{
+    LOKDocView* lokdocview;
+    gchar* dialogid;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(GtvLokDialog, gtv_lok_dialog, GTK_TYPE_DIALOG);
+
+enum
+{
+    PROP_0,
+    PROP_LOKDOCVIEW_CONTEXT,
+    PROP_DIALOG_ID,
+    PROP_LAST
+};
+
+static GParamSpec* properties[PROP_LAST];
+
+static GtvLokDialogPrivate*
+getPrivate(GtvLokDialog* dialog)
+{
+    return static_cast<GtvLokDialogPrivate*>(gtv_lok_dialog_get_instance_private(dialog));
+}
+
+static void
+gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
+{
+    GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
+    GtvLokDialogPrivate* priv = getPrivate(pDialog);
+
+    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);
+    gtk_widget_set_size_request(GTK_WIDGET(pDialogDrawingArea), nWidth, nHeight);
+
+    cairo_surface_flush(pSurface);
+    cairo_surface_mark_dirty(pSurface);
+
+    cairo_set_source_surface(pCairo, pSurface, 0, 0);
+    cairo_paint(pCairo);
+}
+
+static void
+gtv_lok_dialog_init(GtvLokDialog* dialog)
+{
+    GtkWidget* pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+    GtkWidget* pDialogDrawingArea = gtk_drawing_area_new();
+
+    g_signal_connect(G_OBJECT(pDialogDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_draw), nullptr);
+    gtk_container_add(GTK_CONTAINER(pContentArea), pDialogDrawingArea);
+}
+
+static void
+gtv_lok_dialog_set_property(GObject* object, guint propId, const GValue* value, GParamSpec* pspec)
+{
+    GtvLokDialog* self = GTV_LOK_DIALOG(object);
+    GtvLokDialogPrivate* priv = getPrivate(self);
+
+    switch(propId)
+    {
+    case PROP_LOKDOCVIEW_CONTEXT:
+        priv->lokdocview = LOK_DOC_VIEW(g_value_get_object(value));
+        break;
+    case PROP_DIALOG_ID:
+        priv->dialogid = g_value_dup_string(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
+    }
+}
+
+static void
+gtv_lok_dialog_get_property(GObject* object, guint propId, GValue* value, GParamSpec* pspec)
+{
+    GtvLokDialog* self = GTV_LOK_DIALOG(object);
+    GtvLokDialogPrivate* priv = getPrivate(self);
+
+    switch(propId)
+    {
+    case PROP_LOKDOCVIEW_CONTEXT:
+        g_value_set_object(value, priv->lokdocview);
+        break;
+    case PROP_DIALOG_ID:
+        g_value_set_pointer(value, priv->dialogid);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
+    }
+}
+
+static void
+gtv_lok_dialog_finalize(GObject* object)
+{
+    GtvLokDialog* self = GTV_LOK_DIALOG(object);
+    GtvLokDialogPrivate* priv = getPrivate(self);
+
+    g_free(priv->dialogid);
+
+    G_OBJECT_CLASS(gtv_lok_dialog_parent_class)->finalize(object);
+}
+
+static void
+gtv_lok_dialog_class_init(GtvLokDialogClass* klass)
+{
+    G_OBJECT_CLASS(klass)->get_property = gtv_lok_dialog_get_property;
+    G_OBJECT_CLASS(klass)->set_property = gtv_lok_dialog_set_property;
+    G_OBJECT_CLASS(klass)->finalize = gtv_lok_dialog_finalize;
+
+    properties[PROP_LOKDOCVIEW_CONTEXT] = g_param_spec_object("lokdocview",
+                                                              "LOKDocView Context",
+                                                              "The LOKDocView context object to be used for dialog rendering",
+                                                              LOK_TYPE_DOC_VIEW,
+                                                              static_cast<GParamFlags>(G_PARAM_READWRITE |
+                                                                                       G_PARAM_CONSTRUCT_ONLY |
+                                                                                       G_PARAM_STATIC_STRINGS));
+
+    properties[PROP_DIALOG_ID] = g_param_spec_string("dialogid",
+                                                     "Dialog identifier",
+                                                     "Unique dialog identifier; UNO command for now",
+                                                     nullptr,
+                                                     static_cast<GParamFlags>(G_PARAM_READWRITE |
+                                                                              G_PARAM_CONSTRUCT_ONLY |
+                                                                              G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_properties (G_OBJECT_CLASS(klass), PROP_LAST, properties);
+}
+
+GtkWidget*
+gtv_lok_dialog_new(LOKDocView* pDocView, const gchar* dialogId)
+{
+    GtkWindow* pWindow = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
+    return GTK_WIDGET(g_object_new(GTV_TYPE_LOK_DIALOG,
+                                   "lokdocview", pDocView,
+                                   "dialogid", dialogId,
+                                   "title", "LOK Dialog",
+                                   "modal", false,
+                                   "transient-for", pWindow,
+                                   nullptr));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
new file mode 100644
index 000000000000..650d816e7e4a
--- /dev/null
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef GTV_LOK_DIALOG_H
+#define GTV_LOK_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#include <LibreOfficeKit/LibreOfficeKitGtk.h>
+
+G_BEGIN_DECLS
+
+#define GTV_TYPE_LOK_DIALOG            (gtv_lok_dialog_get_type())
+#define GTV_LOK_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GTV_TYPE_LOK_DIALOG, GtvLokDialog))
+#define GTV_IS_LOK_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTV_TYPE_LOK_DIALOG))
+#define GTV_LOK_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  GTV_TYPE_LOK_DIALOG, GtvLokDialogClass))
+#define GTV_IS_LOK_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  GTV_TYPE_LOK_DIALOG))
+#define GTV_LOK_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  GTV_TYPE_LOK_DIALOG, GtvLokDialogClass))
+
+struct GtvLokDialog
+{
+    GtkDialog parent;
+};
+
+struct GtvLokDialogClass
+{
+    GtkDialogClass parentClass;
+};
+
+GType gtv_lok_dialog_get_type               (void) G_GNUC_CONST;
+
+GtkWidget* gtv_lok_dialog_new(LOKDocView* pDocView, const gchar* dialogId);
+
+G_END_DECLS
+
+#endif /* GTV_LOK_DIALOG_H */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.cxx b/libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.cxx
index 0da85fd89e65..108b3003ef1f 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-main-toolbar.cxx
@@ -14,6 +14,7 @@
 #include <gtv-signal-handlers.hxx>
 #include <gtv-helpers.hxx>
 #include <gtv-calc-header-bar.hxx>
+#include <gtv-lok-dialog.hxx>
 
 #include <map>
 #include <memory>
@@ -34,6 +35,7 @@ struct GtvMainToolbarPrivateImpl
     GtkWidget* m_pDeleteComment;
     GtkWidget* m_pPartSelector;
     GtkWidget* m_pPartModeSelector;
+    GtkWidget* m_pDialogSelector;
 
     /// Sensitivity (enabled or disabled) for each tool item, ignoring edit state
     std::map<GtkToolItem*, bool> m_aToolItemSensitivities;
@@ -48,7 +50,8 @@ struct GtvMainToolbarPrivateImpl
         m_pJustifypara(nullptr),
         m_pDeleteComment(nullptr),
         m_pPartSelector(nullptr),
-        m_pPartModeSelector(nullptr)
+        m_pPartModeSelector(nullptr),
+        m_pDialogSelector(nullptr)
         { }
 };
 
@@ -95,6 +98,8 @@ gtv_main_toolbar_init(GtvMainToolbar* toolbar)
     priv->m_pDeleteComment = GTK_WIDGET(gtk_builder_get_object(builder.get(), "btn_removeannotation"));
     priv->m_pPartSelector = GTK_WIDGET(gtk_builder_get_object(builder.get(), "combo_partselector"));
     priv->m_pPartModeSelector = GTK_WIDGET(gtk_builder_get_object(builder.get(), "combo_partsmodeselector"));
+    priv->m_pDialogSelector = GTK_WIDGET(gtk_builder_get_object(builder.get(), "combo_dialogselector"));
+
     toolbar->m_pAddressbar = GTK_WIDGET(gtk_builder_get_object(builder.get(), "addressbar_entry"));
     toolbar->m_pFormulabar = GTK_WIDGET(gtk_builder_get_object(builder.get(), "formulabar_entry"));
 
@@ -113,6 +118,7 @@ gtv_main_toolbar_init(GtvMainToolbar* toolbar)
     gtk_builder_add_callback_symbol(builder.get(), "documentRepair", G_CALLBACK(documentRepair));
     gtk_builder_add_callback_symbol(builder.get(), "signalAddressbar", G_CALLBACK(signalAddressbar));
     gtk_builder_add_callback_symbol(builder.get(), "signalFormulabar", G_CALLBACK(signalFormulabar));
+    gtk_builder_add_callback_symbol(builder.get(), "openLokDialog", G_CALLBACK(openLokDialog));
 
     // find toolbar
     // Note: These buttons are not the part of GtvMainToolbar
@@ -175,6 +181,22 @@ static void populatePartSelector(GtvMainToolbar* toolbar)
     gtv_application_window_set_part_broadcast(window, true);
 }
 
+static void populateDialogSelector(GtvMainToolbar* toolbar)
+{
+    GtvMainToolbarPrivate& priv = getPrivate(toolbar);
+
+    GtkComboBoxText* pSelector = GTK_COMBO_BOX_TEXT(priv->m_pDialogSelector);
+    gtk_combo_box_text_append_text( pSelector, ".uno:SearchDialog" );
+    gtk_combo_box_text_append_text( pSelector, ".uno:AcceptTrackedChanges" );
+    gtk_combo_box_text_append_text( pSelector, ".uno:SpellingAndGrammarDialog" );
+    gtk_combo_box_text_append_text( pSelector, ".uno:InsertField" );
+    gtk_combo_box_text_append_text( pSelector, ".uno:ImageMapDialog" );
+    gtk_combo_box_text_append_text( pSelector, ".uno:WordCountDialog" );
+    gtk_combo_box_text_append_text( pSelector, ".uno:HyperlinkDialog" );
+    gtk_combo_box_text_append_text( pSelector, ".uno:InsertIndexesEntry" );
+    gtk_combo_box_text_append_text( pSelector, ".uno:InsertAuthoritiesEntry");
+}
+
 void
 gtv_main_toolbar_doc_loaded(GtvMainToolbar* toolbar, LibreOfficeKitDocumentType eDocType, bool bEditMode)
 {
@@ -201,6 +223,8 @@ gtv_main_toolbar_doc_loaded(GtvMainToolbar* toolbar, LibreOfficeKitDocumentType
 
     // populate combo boxes
     populatePartSelector(toolbar);
+    // populate dialogs
+    populateDialogSelector(toolbar);
 }
 
 GtkContainer*
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
index 3c9ee3e405f2..5b3b113d0a6e 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
@@ -12,6 +12,7 @@
 #include <gtv-application-window.hxx>
 #include <gtv-helpers.hxx>
 #include <gtv-lokdocview-signal-handlers.hxx>
+#include <gtv-lok-dialog.hxx>
 
 #include <sal/types.h>
 
@@ -281,6 +282,18 @@ void changePartMode( GtkWidget* pSelector, gpointer /* pItem */ )
     }
 }
 
+void openLokDialog( GtkWidget* pSelector, gpointer /*pItem*/ )
+{
+    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(pSelector));
+    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);
+    g_free(pDialogId);
+
+    gtk_window_set_resizable(GTK_WINDOW(pDialog), false);
+    gtk_widget_show_all(GTK_WIDGET(pDialog));
+    gtk_window_present(GTK_WINDOW(pDialog));
+}
+
 void changeZoom( GtkWidget* pButton, gpointer /* pItem */ )
 {
     static const float fZooms[] = { 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, 5.0 };
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.hxx b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.hxx
index a19a7b5cd744..8ec37a66f552 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.hxx
@@ -28,6 +28,8 @@ void changePartMode( GtkWidget* pSelector, gpointer /* pItem */ );
 
 void changePart( GtkWidget* pSelector, gpointer /*pItem*/ );
 
+void openLokDialog( GtkWidget* pSelector, gpointer /*pItem*/ );
+
 void changeZoom( GtkWidget* pButton, gpointer /* pItem */ );
 
 void toggleFindbar(GtkWidget* pButton, gpointer /*pItem*/);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv.ui b/libreofficekit/qa/gtktiledviewer/gtv.ui
index e27f79714a4b..2dfe219c44f0 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv.ui
+++ b/libreofficekit/qa/gtktiledviewer/gtv.ui
@@ -445,6 +445,23 @@
       </packing>
     </child>
     <child>
+      <object class="GtkToolItem" id="dialogselectortoolitem">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkComboBoxText" id="combo_dialogselector">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <signal name="changed" handler="openLokDialog" swapped="no"/>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="homogeneous">True</property>
+      </packing>
+    </child>
+    <child>
       <object class="GtkToggleToolButton" id="btn_editmode">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
commit 2c426732a5a699b131733288beed5ff2cc7d203c
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jul 28 18:05:20 2017 +0530

    lokdialog: Better dialog rendering API
    
    After painting the dialog, also write width and height of the rendered
    dialog. The dialog is rendered
    always on the top left of the given canvas, so client can crop the
    canvas accordingly.
    
    Change-Id: If052058a6db8a85d4e28ec88cffcca05564b17f0

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index dbc2e029889e..ea81c5e551b5 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -18,6 +18,8 @@
 #include <com/sun/star/util/XModifiable.hpp>
 #include <com/sun/star/text/TextContentAnchorType.hpp>
 #include <boost/property_tree/json_parser.hpp>
+
+#include <vcl/scheduler.hxx>
 #include <comphelper/processfactory.hxx>
 #include <rtl/uri.hxx>
 #include <sfx2/objsh.hxx>
@@ -2161,12 +2163,10 @@ void DesktopLOKTest::testDialogsWriter()
     sal_Int32 nStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, nCanvasWidth);
     std::vector<unsigned char> aBuffer(nStride * nCanvasHeight);
 
-    pDocument->pClass->paintDialog(pDocument, aBuffer.data(), nCanvasWidth, nCanvasHeight);
+    pDocument->pClass->paintDialog(pDocument, ".uno:WordCountDialog", aBuffer.data(), &nCanvasWidth, &nCanvasHeight);
 
     cairo_surface_t* pSurface = cairo_image_surface_create_for_data(aBuffer.data(), CAIRO_FORMAT_ARGB32, nCanvasWidth, nCanvasHeight, nStride);
     cairo_surface_write_to_png(pSurface, "/tmp/dialog.png");
-
-    CPPUNIT_ASSERT(false);
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest);
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index bc41b0994157..6c99fed756ab 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -583,7 +583,7 @@ static unsigned char* doc_renderFont(LibreOfficeKitDocument* pThis,
                           int* pFontHeight);
 static char* doc_getPartHash(LibreOfficeKitDocument* pThis, int nPart);
 
-static void doc_paintDialog(LibreOfficeKitDocument* pThis, unsigned char* pBuffer, int nWidth, int nHeight);
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
 LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XComponent> &xComponent)
     : mxComponent(xComponent)
@@ -2913,7 +2913,7 @@ unsigned char* doc_renderFont(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pTh
     return nullptr;
 }
 
-static void doc_paintDialog(LibreOfficeKitDocument* pThis, unsigned char* pBuffer, int nWidth, int nHeight)
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight)
 {
     SolarMutexGuard aGuard;
 
@@ -2922,11 +2922,11 @@ static void doc_paintDialog(LibreOfficeKitDocument* pThis, unsigned char* pBuffe
     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(pDialogRenderable->findDialog());
+    vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
 
-    pDialogRenderable->paintDialog(aDialogID, *pDevice.get(), nWidth, nHeight);
+    pDialogRenderable->paintDialog(aDialogID, *pDevice.get(), *nWidth, *nHeight);
 }
 
 static char* lo_getError (LibreOfficeKit *pThis)
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index 18694092c2fa..2621ec03947a 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -14,26 +14,29 @@
 #include <tools/gen.hxx>
 #include <vcl/pointr.hxx>
 #include <vcl/virdev.hxx>
+#include <vcl/window.hxx>
+
+#include "IDialogRenderable.hxx"
+
+#include <map>
 
 namespace vcl
 {
 
-typedef sal_Int32 DialogID;
+typedef OUString DialogID;
 
 class VCL_DLLPUBLIC IDialogRenderable
 {
 public:
     virtual ~IDialogRenderable();
 
-    virtual DialogID findDialog() = 0;
-
-    virtual void paintDialog(DialogID rDialogID, VirtualDevice &rDevice,
-                             int nOutputWidth, int nOutputHeight) = 0;
+    virtual void paintDialog(const DialogID& rDialogID, VirtualDevice &rDevice,
+                             int& nOutputWidth, int& nOutputHeight) = 0;
 
-    virtual void postDialogMouseEvent(DialogID rDialogID, int nType,
+    virtual void postDialogMouseEvent(const DialogID& rDialogID, int nType,
                                       int nCharCode, int nKeyCode) = 0;
 
-    virtual void postDialogKeyEvent(DialogID rDialogID, int nType, int nX, int nY,
+    virtual void postDialogKeyEvent(const DialogID& rDialogID, int nType, int nX, int nY,
                                     int nCount, int nButtons, int nModifier) = 0;
 };
 
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 49737fdc6057..e452b9f50f48 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -101,6 +101,9 @@ public:
     virtual void PrePaint(vcl::RenderContext& rRenderContext) override;
     virtual void PostPaint(vcl::RenderContext& rRenderContext) override;
 
+    // Paints the current dialog to the given virtual device
+    void paintDialog(VirtualDevice& rDevice);
+
     // ensureRepaint - triggers Application::Yield until the dialog is
     // completely repainted. Sometimes needed for dialogs showing progress
     // during actions
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index f2dc662e299f..ea5fdce243a0 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -426,12 +426,11 @@ public:
     /// @see vcl::ITiledRenderable::getPostIts().
     OUString getPostIts() override;
 
-    vcl::DialogID findDialog() override;
-    void paintDialog(vcl::DialogID rDialogID, VirtualDevice &rDevice, int nWidth, int nHeight) override;
-    void postDialogMouseEvent(vcl::DialogID rDialogID, int nType,
+    void paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight) override;
+    void postDialogMouseEvent(const vcl::DialogID& rDialogID, int nType,
                              int nCharCode, int nKeyCode) override;
 
-    void postDialogKeyEvent(vcl::DialogID rDialogID, int nType, int nX, int nY,
+    void postDialogKeyEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
                             int nCount, int nButtons, int nModifier) override;
 
     // css::tiledrendering::XTiledRenderable
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index f8fd02e7799d..f30028a92dff 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -33,6 +33,8 @@
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/sfxbasecontroller.hxx>
 #include <sfx2/docfile.hxx>
+#include <sfx2/msg.hxx>
+#include <sfx2/msgpool.hxx>
 #include <sfx2/printer.hxx>
 #include <toolkit/helper/vclunohelper.hxx>
 #include <toolkit/awt/vclxdevice.hxx>
@@ -3550,32 +3552,35 @@ void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_I
     #endif
 }
 
-vcl::DialogID SwXTextDocument::findDialog()
+void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight)
 {
-    return vcl::DialogID(0);
-}
-
-void SwXTextDocument::paintDialog(vcl::DialogID /*rDialogID*/, VirtualDevice& rDevice, int nWidth, int nHeight)
-{
-    SfxViewShell* pViewShell = pDocShell->GetView();
-    SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
-    SfxChildWindow* pSfxChildWindow = SwSpellDialogChildWindow::CreateImpl(&pViewFrame->GetWindow(), SwSpellDialogChildWindow::GetChildWindowId(),
-                                                                           &pViewFrame->GetBindings(), nullptr);
-
-    Size aSize(nWidth, nHeight);
-
-    vcl::Window* pWindow = pSfxChildWindow->GetWindow();
+    SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
+    SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
+    const SfxSlot* pSlot = pSlotPool->GetUnoSlot(rDialogID);
+    SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
+    if (!pChild)
+    {
+        pViewFrame->ToggleChildWindow(pSlot->GetSlotId());
+        pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
+        if (!pChild)
+        {
+            SAL_WARN("lok.dialog", "Dialog " << rDialogID << " is not supported");
+            return;
+        }
+    }
 
-    pWindow->SetSizePixel(aSize);
-    pWindow->Show();
-    pWindow->Paint(rDevice, tools::Rectangle(Point(), aSize));
+    Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
+    pDlg->paintDialog(rDevice);
+    const Size aSize = pDlg->GetOptimalSize();
+    nWidth = aSize.getWidth();
+    nHeight = aSize.getHeight();
 }
 
-void SwXTextDocument::postDialogMouseEvent(vcl::DialogID /*rDialogID*/, int /*nType*/, int /*nCharCode*/, int /*nKeyCode*/)
+void SwXTextDocument::postDialogMouseEvent(const vcl::DialogID& /*rDialogID*/, int /*nType*/, int /*nCharCode*/, int /*nKeyCode*/)
 {
 }
 
-void SwXTextDocument::postDialogKeyEvent(vcl::DialogID /*rDialogID*/, int /*nType*/, int /*nX*/, int /*nY*/,
+void SwXTextDocument::postDialogKeyEvent(const vcl::DialogID& /*rDialogID*/, int /*nType*/, int /*nX*/, int /*nY*/,
                                          int /*nCount*/, int /*nButtons*/, int /*nModifier*/)
 {
 }
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index aa25bae8c74b..58f7d505b6ba 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -51,6 +51,7 @@
 #include <vcl/settings.hxx>
 #include <vcl/uitest/uiobject.hxx>
 #include <vcl/uitest/logger.hxx>
+#include <vcl/virdev.hxx>
 #include <salframe.hxx>
 
 #include <iostream>
@@ -847,6 +848,17 @@ bool Dialog::selectPageByUIXMLDescription(const OString& /*rUIXMLDescription*/)
     return true;
 }
 
+void Dialog::paintDialog(VirtualDevice& rDevice)
+{
+    setDeferredProperties();
+    ImplAdjustNWFSizes();
+    Show();
+    ToTop();
+    ensureRepaint();
+
+    PaintToDevice(&rDevice, Point(0, 0), Size());
+}
+
 void Dialog::ensureRepaint()
 {
     // ensure repaint
commit ce9d1259f3a4eb347c958d96f0eca8dc002c011d
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jul 28 16:34:56 2017 +0530

    Include dialogID in paintDialog API
    
    Change-Id: I6bc624272138f0e23d2e3abfd82b857fed12e12c

diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 717b5b3d348c..a37b2ecdb13d 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -255,7 +255,7 @@ struct _LibreOfficeKitDocumentClass
                        size_t nSize);
 
     /// WIP
-    void (*paintDialog) (LibreOfficeKitDocument* pThis, unsigned char* pBuffer, int nWidth, int nHeight);
+    void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
 #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
 };
commit 3ac08c7d1fe9e4bbe8e044c6a8225e792507ed5a
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Jun 30 14:20:19 2017 +0530

    Write the dialog rendering to file
    
    Change-Id: I7b10f9ee6e1f914e85ded8756b80c17a505ee0fc

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index d705e6c8ed97..dbc2e029889e 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -2156,22 +2156,15 @@ void DesktopLOKTest::testExtractParameter()
 void DesktopLOKTest::testDialogsWriter()
 {
     LibLODocument_Impl* pDocument = loadDoc("blank_text.odt");
-    int nCanvasWidth = 100;
-    int nCanvasHeight = 300;
+    int nCanvasWidth = 800;
+    int nCanvasHeight = 600;
     sal_Int32 nStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, nCanvasWidth);
     std::vector<unsigned char> aBuffer(nStride * nCanvasHeight);
 
     pDocument->pClass->paintDialog(pDocument, aBuffer.data(), nCanvasWidth, nCanvasHeight);
 
-    for (long y = 0; y < nCanvasHeight; ++y)
-    {
-        unsigned char* c = &aBuffer.data()[y * nStride];
-        for (long x = 0; x < nStride; ++x)
-        {
-            printf ("%02x ", c[x]);
-        }
-        printf ("\n");
-    }
+    cairo_surface_t* pSurface = cairo_image_surface_create_for_data(aBuffer.data(), CAIRO_FORMAT_ARGB32, nCanvasWidth, nCanvasHeight, nStride);
+    cairo_surface_write_to_png(pSurface, "/tmp/dialog.png");
 
     CPPUNIT_ASSERT(false);
 }
commit 75f9a668d8dcd4136ad284d66f2fabe3ab3d9bde
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Jun 22 12:20:01 2017 +0200

    Instantiate spell dialog and paint in a paintDialog call
    
    Change-Id: I7bd7f9cb33cd79d1e55ce51fe39917c5741bdf18

diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index b6614780666a..f8fd02e7799d 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -164,6 +164,7 @@
 #include <svx/svdview.hxx>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/servicehelper.hxx>
+#include <SwSpellDialogChildWindow.hxx>
 #include <memory>
 
 using namespace ::com::sun::star;
@@ -3554,12 +3555,20 @@ vcl::DialogID SwXTextDocument::findDialog()
     return vcl::DialogID(0);
 }
 
-void SwXTextDocument::paintDialog(vcl::DialogID /*rDialogID*/, VirtualDevice& /*rDevice*/, int /*nWidth*/, int /*nHeight*/)
+void SwXTextDocument::paintDialog(vcl::DialogID /*rDialogID*/, VirtualDevice& rDevice, int nWidth, int nHeight)
 {
-    //SwViewShell* pViewShell = pDocShell->GetWrtShell();
+    SfxViewShell* pViewShell = pDocShell->GetView();
+    SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
+    SfxChildWindow* pSfxChildWindow = SwSpellDialogChildWindow::CreateImpl(&pViewFrame->GetWindow(), SwSpellDialogChildWindow::GetChildWindowId(),
+                                                                           &pViewFrame->GetBindings(), nullptr);
 
-    //SwSpellDialogChildWindow::CreateImpl(nullptr, SwSpellDialogChildWindow::GetChildWindowId(),
-    //                                     pViewShell->GetBindings(), );
+    Size aSize(nWidth, nHeight);
+
+    vcl::Window* pWindow = pSfxChildWindow->GetWindow();
+
+    pWindow->SetSizePixel(aSize);
+    pWindow->Show();
+    pWindow->Paint(rDevice, tools::Rectangle(Point(), aSize));
 }
 
 void SwXTextDocument::postDialogMouseEvent(vcl::DialogID /*rDialogID*/, int /*nType*/, int /*nCharCode*/, int /*nKeyCode*/)
commit fe09912171c17fbb82df88932aa53a931d04262d
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Jun 22 12:18:26 2017 +0200

    Test for paintDialog to show if we succeed to paint into a VD
    
    Change-Id: Iccba81ff4326f1fb3d93bdf9393d7d3cc3675f9e

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 58aea8beb431..d705e6c8ed97 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -39,7 +39,7 @@
 #include <cairo.h>
 #include <ostream>
 #include <config_features.h>
-#include <vcl/scheduler.hxx>
+#include <png.h>
 
 #include <lib/init.hxx>
 
@@ -115,6 +115,7 @@ public:
     void testCommentsCallbacksWriter();
     void testRunMacro();
     void testExtractParameter();
+    void testDialogsWriter();
 
     CPPUNIT_TEST_SUITE(DesktopLOKTest);
     CPPUNIT_TEST(testGetStyles);
@@ -157,6 +158,7 @@ public:
     CPPUNIT_TEST(testCommentsCallbacksWriter);
     CPPUNIT_TEST(testRunMacro);
     CPPUNIT_TEST(testExtractParameter);
+    CPPUNIT_TEST(testDialogsWriter);
     CPPUNIT_TEST_SUITE_END();
 
     uno::Reference<lang::XComponent> mxComponent;
@@ -178,7 +180,6 @@ public:
     // for testContextMenu{Calc, Writer}
     osl::Condition m_aContextMenuCondition;
     boost::property_tree::ptree m_aContextMenuResult;
-
 };
 
 LibLODocument_Impl* DesktopLOKTest::loadDoc(const char* pName, LibreOfficeKitDocumentType eType)
@@ -2152,6 +2153,29 @@ void DesktopLOKTest::testExtractParameter()
     CPPUNIT_ASSERT_EQUAL(OUString("Something1,Something2=blah,Something3"), aOptions);
 }
 
+void DesktopLOKTest::testDialogsWriter()
+{
+    LibLODocument_Impl* pDocument = loadDoc("blank_text.odt");
+    int nCanvasWidth = 100;
+    int nCanvasHeight = 300;
+    sal_Int32 nStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, nCanvasWidth);
+    std::vector<unsigned char> aBuffer(nStride * nCanvasHeight);
+
+    pDocument->pClass->paintDialog(pDocument, aBuffer.data(), nCanvasWidth, nCanvasHeight);
+
+    for (long y = 0; y < nCanvasHeight; ++y)
+    {
+        unsigned char* c = &aBuffer.data()[y * nStride];
+        for (long x = 0; x < nStride; ++x)
+        {
+            printf ("%02x ", c[x]);
+        }
+        printf ("\n");
+    }
+
+    CPPUNIT_ASSERT(false);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit c32456a2f7525fbabdcde1a12a6b9947ba9118fa
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri May 26 22:55:31 2017 +0200

    Add IDialogRenderable interface for rendering of dialogs
    
    Change-Id: I1d85729a1ac1a99d33ea2bde1b50ccf4c05ca9a9

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index be81a0fca0b0..bc41b0994157 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -77,6 +77,7 @@
 #include <vcl/sysdata.hxx>
 #include <vcl/virdev.hxx>
 #include <vcl/ITiledRenderable.hxx>
+#include <vcl/IDialogRenderable.hxx>
 #include <unicode/uchar.h>
 #include <unotools/configmgr.hxx>
 #include <unotools/syslocaleoptions.hxx>
@@ -582,6 +583,8 @@ static unsigned char* doc_renderFont(LibreOfficeKitDocument* pThis,
                           int* pFontHeight);
 static char* doc_getPartHash(LibreOfficeKitDocument* pThis, int nPart);
 
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, unsigned char* pBuffer, int nWidth, int nHeight);
+
 LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XComponent> &xComponent)
     : mxComponent(xComponent)
 {
@@ -628,6 +631,8 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
         m_pDocumentClass->renderFont = doc_renderFont;
         m_pDocumentClass->getPartHash = doc_getPartHash;
 
+        m_pDocumentClass->paintDialog = doc_paintDialog;
+
         gDocumentClass = m_pDocumentClass;
     }
     pClass = m_pDocumentClass.get();
@@ -1144,6 +1149,12 @@ ITiledRenderable* getTiledRenderable(LibreOfficeKitDocument* pThis)
     return dynamic_cast<ITiledRenderable*>(pDocument->mxComponent.get());
 }
 
+IDialogRenderable* getDialogRenderable(LibreOfficeKitDocument* pThis)
+{
+    LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis);
+    return dynamic_cast<IDialogRenderable*>(pDocument->mxComponent.get());
+}
+
 } // anonymous namespace
 
 // Wonder global state ...
@@ -2902,6 +2913,22 @@ unsigned char* doc_renderFont(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pTh
     return nullptr;
 }
 
+static void doc_paintDialog(LibreOfficeKitDocument* pThis, unsigned char* pBuffer, int nWidth, int nHeight)
+{
+    SolarMutexGuard aGuard;
+
+    IDialogRenderable* pDialogRenderable = getDialogRenderable(pThis);
+
+    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);
+
+    vcl::DialogID aDialogID(pDialogRenderable->findDialog());
+
+    pDialogRenderable->paintDialog(aDialogID, *pDevice.get(), nWidth, nHeight);
+}
+
 static char* lo_getError (LibreOfficeKit *pThis)
 {
     SolarMutexGuard aGuard;
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index a4035c7351f0..717b5b3d348c 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -254,6 +254,9 @@ struct _LibreOfficeKitDocumentClass
                        int* pArray,
                        size_t nSize);
 
+    /// WIP
+    void (*paintDialog) (LibreOfficeKitDocument* pThis, unsigned char* pBuffer, int nWidth, int nHeight);
+
 #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
 };
 
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
new file mode 100644
index 000000000000..18694092c2fa
--- /dev/null
+++ b/include/vcl/IDialogRenderable.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef INCLUDED_VCL_IDIALOGRENDERABLE_HXX
+#define INCLUDED_VCL_IDIALOGRENDERABLE_HXX
+
+#include <tools/gen.hxx>
+#include <vcl/pointr.hxx>
+#include <vcl/virdev.hxx>
+
+namespace vcl
+{
+
+typedef sal_Int32 DialogID;
+
+class VCL_DLLPUBLIC IDialogRenderable
+{
+public:
+    virtual ~IDialogRenderable();
+
+    virtual DialogID findDialog() = 0;
+
+    virtual void paintDialog(DialogID rDialogID, VirtualDevice &rDevice,
+                             int nOutputWidth, int nOutputHeight) = 0;
+
+    virtual void postDialogMouseEvent(DialogID rDialogID, int nType,
+                                      int nCharCode, int nKeyCode) = 0;
+
+    virtual void postDialogKeyEvent(DialogID rDialogID, int nType, int nX, int nY,
+                                    int nCount, int nButtons, int nModifier) = 0;
+};
+
+} // namespace vcl
+
+#endif // INCLUDED_VCL_IDIALOGRENDERABLE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index ccbfb62589cd..f2dc662e299f 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -69,6 +69,7 @@
 #include <cppuhelper/implbase.hxx>
 #include <vcl/event.hxx>
 #include <vcl/ITiledRenderable.hxx>
+#include <vcl/IDialogRenderable.hxx>
 #include <com/sun/star/tiledrendering/XTiledRenderable.hpp>
 
 #include <unobaseclass.hxx>
@@ -130,6 +131,7 @@ class SW_DLLPUBLIC SwXTextDocument : public SwXTextDocumentBaseClass,
     public SvxFmMSFactory,
     public SfxBaseModel,
     public vcl::ITiledRenderable,
+    public vcl::IDialogRenderable,
     public css::tiledrendering::XTiledRenderable
 {
 private:
@@ -423,6 +425,15 @@ public:
     OUString getTrackedChangeAuthors() override;
     /// @see vcl::ITiledRenderable::getPostIts().
     OUString getPostIts() override;
+
+    vcl::DialogID findDialog() override;
+    void paintDialog(vcl::DialogID rDialogID, VirtualDevice &rDevice, int nWidth, int nHeight) override;
+    void postDialogMouseEvent(vcl::DialogID rDialogID, int nType,
+                             int nCharCode, int nKeyCode) override;
+
+    void postDialogKeyEvent(vcl::DialogID rDialogID, int nType, int nX, int nY,
+                            int nCount, int nButtons, int nModifier) override;
+
     // css::tiledrendering::XTiledRenderable
     virtual void SAL_CALL paintTile( const ::css::uno::Any& Parent, ::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, ::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight ) override;
 
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index aca79a13c678..b6614780666a 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3549,6 +3549,28 @@ void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_I
     #endif
 }
 
+vcl::DialogID SwXTextDocument::findDialog()
+{
+    return vcl::DialogID(0);
+}
+
+void SwXTextDocument::paintDialog(vcl::DialogID /*rDialogID*/, VirtualDevice& /*rDevice*/, int /*nWidth*/, int /*nHeight*/)
+{
+    //SwViewShell* pViewShell = pDocShell->GetWrtShell();
+
+    //SwSpellDialogChildWindow::CreateImpl(nullptr, SwSpellDialogChildWindow::GetChildWindowId(),
+    //                                     pViewShell->GetBindings(), );
+}
+
+void SwXTextDocument::postDialogMouseEvent(vcl::DialogID /*rDialogID*/, int /*nType*/, int /*nCharCode*/, int /*nKeyCode*/)
+{
+}
+
+void SwXTextDocument::postDialogKeyEvent(vcl::DialogID /*rDialogID*/, int /*nType*/, int /*nX*/, int /*nY*/,
+                                         int /*nCount*/, int /*nButtons*/, int /*nModifier*/)
+{
+}
+
 void * SAL_CALL SwXTextDocument::operator new( size_t t) throw()
 {
     return SwXTextDocumentBaseClass::operator new(t);
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 0c62ba2c4366..4790fe7094b5 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -338,6 +338,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/app/IconThemeScanner \
     vcl/source/app/IconThemeSelector \
     vcl/source/app/ITiledRenderable \
+    vcl/source/app/IDialogRenderable \
     vcl/source/app/sound \
     vcl/source/app/stdtext \
     vcl/source/app/svapp \
diff --git a/vcl/source/app/IDialogRenderable.cxx b/vcl/source/app/IDialogRenderable.cxx
new file mode 100644
index 000000000000..58ec05265101
--- /dev/null
+++ b/vcl/source/app/IDialogRenderable.cxx
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <vcl/IDialogRenderable.hxx>
+
+namespace vcl
+{
+
+IDialogRenderable::~IDialogRenderable()
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 54b67d3e23c6fab3d74ba05437edd3844c7c1d37
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri May 26 22:37:06 2017 +0200

    move ITileRenderable implementation to own file
    
    Change-Id: Ib05ecf5f92e0ae4adf99c4dd10d60e730a95cf45

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 6b40a48d8783..0c62ba2c4366 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -337,6 +337,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/app/IconThemeInfo \
     vcl/source/app/IconThemeScanner \
     vcl/source/app/IconThemeSelector \
+    vcl/source/app/ITiledRenderable \
     vcl/source/app/sound \
     vcl/source/app/stdtext \
     vcl/source/app/svapp \
diff --git a/vcl/source/app/ITiledRenderable.cxx b/vcl/source/app/ITiledRenderable.cxx
new file mode 100644
index 000000000000..3eb5dcd2da6e
--- /dev/null
+++ b/vcl/source/app/ITiledRenderable.cxx
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <vcl/ITiledRenderable.hxx>
+
+namespace vcl
+{
+
+ITiledRenderable::~ITiledRenderable()
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx
index 52bb9f566873..974533d9ea13 100644
--- a/vcl/source/gdi/virdev.cxx
+++ b/vcl/source/gdi/virdev.cxx
@@ -23,18 +23,8 @@
 #include "outdev.h"
 #include "PhysicalFontCollection.hxx"
 #include "svdata.hxx"
-
 #include <vcl/ITiledRenderable.hxx>
 
-namespace vcl
-{
-
-ITiledRenderable::~ITiledRenderable()
-{
-}
-
-}
-
 using namespace ::com::sun::star::uno;
 
 bool VirtualDevice::AcquireGraphics() const
commit 9c7ebba02b5ed27bfe8dbec3b16f308492acf28c
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Sat Jul 29 02:40:21 2017 +0530

    Fix no longer valid comment
    
    This was changed in d72aad218c9737fb19d1a835b03c13b7107a96c0
    
    Change-Id: Ie93f603c82669ca612fbf9635a62c50e63702a85

diff --git a/solenv/gdb/libreoffice/vcl.py b/solenv/gdb/libreoffice/vcl.py
index d8bac0b84331..a9111838d55d 100644
--- a/solenv/gdb/libreoffice/vcl.py
+++ b/solenv/gdb/libreoffice/vcl.py
@@ -15,12 +15,12 @@ class ImplSchedulerDataPrinter(object):
     '''Prints the ImplSchedulerData linked list.
 
        This can be used to dump the current state of the scheduler via:
-          p *ImplGetSVData()->mpFirstSchedulerData
+          p *ImplGetSVData()->maSchedCtx.mpFirstSchedulerData
 
        This doesn't include currently invoked tasks AKA the stack.
 
        To dump the scheduler stack of invoked tasks use:
-          p *ImplGetSVData()->mpSchedulerStack
+          p *ImplGetSVData()->maSchedCtx.mpSchedulerStack
     '''
 
     def __init__(self, typename, value):


More information about the Libreoffice-commits mailing list