[Libreoffice-commits] core.git: Branch 'feature/lok_dialog' - 3 commits - desktop/source include/LibreOfficeKit include/sfx2 include/vcl libreofficekit/qa libreofficekit/source sfx2/source sw/inc sw/source vcl/source

Pranav Kant pranavk at collabora.co.uk
Thu Aug 3 16:21:50 UTC 2017


 desktop/source/lib/init.cxx                                         |   21 +++
 include/LibreOfficeKit/LibreOfficeKit.h                             |    2 
 include/LibreOfficeKit/LibreOfficeKitEnums.h                        |   20 ++
 include/sfx2/basedlgs.hxx                                           |    2 
 include/sfx2/lokhelper.hxx                                          |    4 
 include/vcl/IDialogRenderable.hxx                                   |    8 +
 include/vcl/dialog.hxx                                              |   12 +
 libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx         |    1 
 libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx                 |   67 +++++++++-
 libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx                 |    4 
 libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx |   24 +++
 libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx |    1 
 libreofficekit/source/gtk/lokdocview.cxx                            |   37 +++++
 sfx2/source/dialog/basedlgs.cxx                                     |    8 -
 sfx2/source/view/lokhelper.cxx                                      |   18 ++
 sw/inc/unotxdoc.hxx                                                 |    5 
 sw/source/uibase/uno/unotxdoc.cxx                                   |   35 +++++
 vcl/source/window/dialog.cxx                                        |   58 ++++++++
 vcl/source/window/floatwin.cxx                                      |   22 ++-
 19 files changed, 328 insertions(+), 21 deletions(-)

New commits:
commit 40aca344d280920d8d5e21270b732c5d15ce8e6a
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Aug 3 14:42:55 2017 +0530

    lokdialog: Support for rendering floating window dialog widgets
    
    Now gtktiledviewer can show floating window dialog widgets when user
    clicks any of such widget in the dialog.
    
    Change-Id: I13d756f236379bc8b2041ed41cb7b502f7fd9b24

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 20face8e65ae..e69627ba0e99 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -598,6 +598,8 @@ 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_paintActiveFloatingWindow(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)
 {
@@ -647,6 +649,7 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
         m_pDocumentClass->getPartHash = doc_getPartHash;
 
         m_pDocumentClass->paintDialog = doc_paintDialog;
+        m_pDocumentClass->paintActiveFloatingWindow = doc_paintActiveFloatingWindow;
 
         gDocumentClass = m_pDocumentClass;
     }
@@ -2976,6 +2979,24 @@ static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId
     comphelper::LibreOfficeKit::setDialogPainting(false);
 }
 
+static void doc_paintActiveFloatingWindow(LibreOfficeKitDocument* pThis, const char* pDialogId, 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 = OUString::createFromAscii(pDialogId);
+
+    comphelper::LibreOfficeKit::setDialogPainting(true);
+    pDialogRenderable->paintActiveFloatingWindow(aDialogID, *pDevice.get(), *nWidth, *nHeight);
+    comphelper::LibreOfficeKit::setDialogPainting(false);
+}
+
 static char* lo_getError (LibreOfficeKit *pThis)
 {
     SolarMutexGuard aGuard;
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index ebb6587a373e..8781b1c78722 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -257,6 +257,8 @@ struct _LibreOfficeKitDocumentClass
     /// WIP
     void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
 
+    void (*paintActiveFloatingWindow) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
+
     /// WIP
     void (*postDialogKeyEvent) (LibreOfficeKitDocument* pThis,
                                 const char* pDialogId,
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 3905cb26ce19..4744eb6a4084 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -508,8 +508,26 @@ typedef enum
     /**
      * Dialog invalidation
      */
-    LOK_CALLBACK_DIALOG_INVALIDATE = 35
+    LOK_CALLBACK_DIALOG_INVALIDATE = 35,
 
+    /**
+     * Invalidation corresponding to dialog's children.
+     * Eg: Floating window etc.
+     *
+     * Payload example:
+     * {
+     *   "dialogID": "SpellDialog",
+     *   "action": "close"
+     * }
+     *
+     * - dialogID is the UNO command of the dialog
+     * - action can be
+     *   - close, means dialog child window is closed now
+     *   - invalidate, means dialog child window is invalidated
+     *     It also means that dialog child window is created if it's the first
+     *     invalidate
+     */
+    LOK_CALLBACK_DIALOG_CHILD = 36
 }
 LibreOfficeKitCallbackType;
 
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index b37480df9da1..b57f30a0ccba 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -42,6 +42,8 @@ public:
     static void notifyOtherView(SfxViewShell* pThisView, SfxViewShell const* pOtherView, int nType, const OString& rKey, const OString& rPayload);
     /// Emits a LOK_CALLBACK_DIALOG_INVALIDATE
     static void notifyDialogInvalidation(const OUString& rPayload);
+    /// 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.
     static void notifyInvalidation(SfxViewShell* pThisView, const OString& rPayload);
     /// A special value to signify 'infinity'.
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index b2c0dee552cd..351839e46d02 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -33,6 +33,9 @@ public:
     virtual void paintDialog(const DialogID& rDialogID, VirtualDevice &rDevice,
                              int& nOutputWidth, int& nOutputHeight) = 0;
 
+    virtual void paintActiveFloatingWindow(const DialogID& rDialogID, VirtualDevice &rDevice,
+                                           int& nOutputWidth, int& nOutputHeight) = 0;
+
     virtual void postDialogKeyEvent(const DialogID& rDialogID, int nType,
                                     int nCharCode, int nKeyCode) = 0;
 
@@ -41,6 +44,8 @@ public:
 
     // Callbacks
     virtual void notifyDialogInvalidation(const DialogID& rDialogID) = 0;
+
+    virtual void notifyDialogChild(const DialogID& rDialogID, const OUString& rAction, const Point& rPos) = 0;
 };
 
 } // namespace vcl
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index e0e3bba35b27..126d358552c3 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -70,6 +70,9 @@ public:
     SAL_DLLPRIVATE bool    IsInClose() const { return mbInClose; }
     virtual        void    doDeferredInit(WinBits nBits) override;
     virtual        void    LogicInvalidate(const tools::Rectangle* pRectangle) override;
+                   void    InvalidateFloatingWindow(const Point& rPos);
+                   void    CloseFloatingWindow();
+                   Size    PaintActiveFloatingWindow(VirtualDevice& rDevice);
 
     /// Necessary to register dialog renderable instance to emit LOK callbacks
     void registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
index 077e2577f384..8a5ff9a56d37 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
@@ -315,6 +315,7 @@ static void setupDocView(GtvApplicationWindow* window)
     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-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-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index bb8800e3d734..1bfb9d538ead 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -32,6 +32,7 @@ struct GtvLokDialogPrivate
 {
     LOKDocView* lokdocview;
     GtkWidget* pDialogDrawingArea;
+    GtkWidget* pFloatingWin;
 
     guint32 m_nLastButtonPressTime;
     guint32 m_nLastButtonReleaseTime;
@@ -79,6 +80,8 @@ 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);
@@ -324,6 +327,7 @@ gtv_lok_dialog_init(GtvLokDialog* dialog)
 
     GtkWidget* pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
     priv->pDialogDrawingArea = gtk_drawing_area_new();
+    priv->pFloatingWin = nullptr;
 
     priv->m_nLastButtonPressTime = 0;
     priv->m_nLastButtonReleaseTime = 0;
@@ -421,14 +425,75 @@ gtv_lok_dialog_class_init(GtvLokDialogClass* klass)
     g_object_class_install_properties (G_OBJECT_CLASS(klass), PROP_LAST, properties);
 }
 
+static void
+gtv_lok_dialog_floating_win_draw(GtkWidget* pDrawingArea, cairo_t* pCairo, gpointer userdata)
+{
+    GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
+    GtvLokDialogPrivate* priv = getPrivate(pDialog);
+
+    g_info("gtv_lok_dialog_floating_win_draw triggered");
+    int nWidth = 800;
+    int nHeight = 600;
+    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->paintActiveFloatingWindow(pDocument, priv->dialogid, pBuffer, &nWidth, &nHeight);
+    g_info("Size of floating window: %d x %d", nWidth, nHeight);
+
+    gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea), nWidth, nHeight);
+    gtk_widget_set_size_request(GTK_WIDGET(pDialog), nWidth, nHeight);
+    gtk_window_resize(GTK_WINDOW(pDialog), nWidth, nHeight);
+
+    cairo_surface_flush(pSurface);
+    cairo_surface_mark_dirty(pSurface);
+
+    cairo_set_source_surface(pCairo, pSurface, 0, 0);
+    cairo_paint(pCairo);
+}
+
 void
 gtv_lok_dialog_invalidate(GtvLokDialog* dialog)
 {
-    // trigger a draw on the drawing area
     GtvLokDialogPrivate* priv = getPrivate(dialog);
+
+    // trigger a draw on the dialog drawing area
     gtk_widget_queue_draw(priv->pDialogDrawingArea);
 }
 
+void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog)
+{
+    g_info("Dialog's floating window invalidate");
+
+    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_position(GTK_WINDOW(priv->pFloatingWin), GTK_WIN_POS_MOUSE);
+    gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
+
+    g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
+
+    gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
+    gtk_widget_show_all(priv->pFloatingWin);
+    gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
+}
+
+void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
+{
+    g_info("Dialog's floating window close");
+
+    GtvLokDialogPrivate* priv = getPrivate(dialog);
+    if (priv->pFloatingWin)
+        gtk_widget_destroy(priv->pFloatingWin);
+}
+
+
 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 0205f2ede3f4..bce9edbadba1 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
@@ -39,6 +39,10 @@ GtkWidget* gtv_lok_dialog_new(LOKDocView* pDocView, const gchar* dialogId);
 
 void gtv_lok_dialog_invalidate(GtvLokDialog* dialog);
 
+void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog);
+
+void gtv_lok_dialog_child_close(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 8f86ecd43ca7..d0778cef473d 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -281,7 +281,7 @@ void LOKDocViewSigHandlers::comment(LOKDocView* pDocView, gchar* pComment, gpoin
     }
 }
 
-void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* /*pDialogId*/, gpointer)
+void LOKDocViewSigHandlers::dialogInvalidate(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);
@@ -300,6 +300,28 @@ void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* /*pDia
 */
 }
 
+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");
+
+  // 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));
+      else if (aAction == "close")
+          gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
+  }
+}
+
 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 73bf9c2860ad..a455c3f1fc4c 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
@@ -26,6 +26,7 @@ namespace LOKDocViewSigHandlers {
     void passwordRequired(LOKDocView* pDocView, char* pUrl, gboolean bModify, gpointer);
     void comment(LOKDocView* pDocView, gchar* pComment, gpointer);
     void dialogInvalidate(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 d3bd91eced2a..1259b221e4e8 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -279,6 +279,7 @@ enum
     PASSWORD_REQUIRED,
     COMMENT,
     DIALOG_INVALIDATE,
+    DIALOG_CHILD,
 
     LAST_SIGNAL
 };
@@ -436,6 +437,8 @@ callbackTypeToString (int nType)
         return "LOK_CALLBACK_COMMENT";
     case LOK_CALLBACK_DIALOG_INVALIDATE:
         return "LOK_CALLBACK_DIALOG_INVALIDATE";
+    case LOK_CALLBACK_DIALOG_CHILD:
+        return "LOK_CALLBACK_DIALOG_CHILD";
     }
     g_assert(false);
     return nullptr;
@@ -1409,6 +1412,9 @@ callback (gpointer pData)
     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_CHILD:
+        g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG_CHILD], 0, pCallback->m_aPayload.c_str());
+        break;
     default:
         g_assert(false);
         break;
@@ -3210,6 +3216,37 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass)
                      g_cclosure_marshal_generic,
                      G_TYPE_NONE, 1,
                      G_TYPE_STRING);
+
+    /**
+     * LOKDocView::dialog-child:
+     * @pDocView: the #LOKDocView on which the signal is emitted
+     * @pPayload: JSON described below:
+     *
+     * Invalidation corresponding to dialog's children.
+     * Eg: Floating window etc.
+     *
+     * Payload example:
+     * {
+     *   "dialogID": "SpellDialog",
+     *   "action": "close"
+     * }
+     *
+     * - dialogID is the UNO command of the dialog
+     * - action can be
+     *   - close, means dialog child window is closed now
+     *   - invalidate, means dialog child window is invalidated
+     *     It also means that dialog child window is created if it's the first
+     *     invalidate
+     */
+    doc_view_signals[DIALOG_CHILD] =
+        g_signal_new("dialog-child",
+                     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*
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 46d736206ddf..c6e9d57027b2 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -157,6 +157,24 @@ void SfxLokHelper::notifyDialogInvalidation(const OUString& rDialogID)
     }
 }
 
+void SfxLokHelper::notifyDialogChild(const OUString& rDialogID, const OUString& rAction, const Point& rPos)
+{
+    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() +
+        OString("\", \"position\": \"") + OString::number(rPos.getX()) + OString(", ") + OString::number(rPos.getY()) +
+        + "\" }";
+
+    while (pViewShell)
+    {
+        pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DIALOG_CHILD, aPayload.getStr());
+        pViewShell = SfxViewShell::GetNext(*pViewShell);
+    }
+}
+
 void SfxLokHelper::notifyInvalidation(SfxViewShell* pThisView, const OString& rPayload)
 {
     OStringBuffer aBuf;
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index c1f575bbee86..5fc7d32c95a2 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -427,6 +427,7 @@ public:
     OUString getPostIts() override;
 
     void paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, 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;
 
@@ -435,6 +436,8 @@ public:
 
     void notifyDialogInvalidation(const vcl::DialogID& rDialogID) override;
 
+    void notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos) 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 c277ce3153dd..830e8acc9629 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3662,6 +3662,33 @@ void SwXTextDocument::notifyDialogInvalidation(const vcl::DialogID& rDialogID)
     SfxLokHelper::notifyDialogInvalidation(rDialogID);
 }
 
+void SwXTextDocument::notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos)
+{
+    SfxLokHelper::notifyDialogChild(rDialogID, rAction, rPos);
+}
+
+void SwXTextDocument::paintActiveFloatingWindow(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight)
+{
+    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;
+
+    Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
+    // register the instance so that vcl::Dialog can emit LOK callbacks
+    const Size aSize = pDlg->PaintActiveFloatingWindow(rDevice);
+    SAL_DEBUG("Size of the floating window :  " << aSize);
+    nWidth = aSize.getWidth();
+    nHeight = aSize.getHeight();
+}
+
 void * SAL_CALL SwXTextDocument::operator new( size_t t) throw()
 {
     return SwXTextDocumentBaseClass::operator new(t);
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 65bb09305752..a0e8aebb152e 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -873,10 +873,51 @@ void Dialog::paintDialog(VirtualDevice& rDevice)
     PaintToDevice(&rDevice, Point(0, 0), Size());
 }
 
-void Dialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+Size Dialog::PaintActiveFloatingWindow(VirtualDevice& rDevice)
+{
+    Size aRet;
+    ImplSVData* pSVData = ImplGetSVData();
+    FloatingWindow* pFirstFloat = pSVData->maWinData.mpFirstFloat;
+    if (pFirstFloat)
+    {
+        // TODO:: run a while loop here and check all the active floating
+        // windows ( chained together, cf. pFirstFloat->mpNextFloat )
+        // For now just assume that the active floating window is the one we
+        // want to render
+        if (pFirstFloat->GetParentDialog() == this)
+        {
+            pFirstFloat->PaintToDevice(&rDevice, Point(0, 0), Size());
+            aRet = ::isLayoutEnabled(pFirstFloat) ? pFirstFloat->get_preferred_size() : pFirstFloat->GetSizePixel();
+        }
+
+        pFirstFloat = nullptr;
+    }
+
+    return aRet;
+}
+
+void Dialog::InvalidateFloatingWindow(const Point& rPos)
 {
+    SAL_DEBUG("Dialog:: Invalidate Floating window");
     if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable && !maID.isEmpty())
     {
+        mpDialogRenderable->notifyDialogChild(maID, "invalidate", rPos);
+    }
+}
+
+void Dialog::CloseFloatingWindow()
+{
+    SAL_DEBUG("Dialog:: close Floating window");
+    if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable && !maID.isEmpty())
+    {
+        mpDialogRenderable->notifyDialogChild(maID, "close", Point(0, 0));
+    }
+}
+
+void Dialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+{
+    if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogRenderable && !maID.isEmpty())
+    {
         mpDialogRenderable->notifyDialogInvalidation(maID);
     }
 }
diff --git a/vcl/source/window/floatwin.cxx b/vcl/source/window/floatwin.cxx
index 23e56ce6e669..44ce96c42843 100644
--- a/vcl/source/window/floatwin.cxx
+++ b/vcl/source/window/floatwin.cxx
@@ -38,6 +38,7 @@ public:
 
     VclPtr<ToolBox> mpBox;
     tools::Rectangle       maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
+    Point maPos; // position of the floating window wrt. parent
 };
 
 FloatingWindow::ImplData::ImplData()
@@ -593,6 +594,17 @@ void FloatingWindow::StateChanged( StateChangedType nType )
 
     SystemWindow::StateChanged( nType );
 
+    if (nType == StateChangedType::InitShow && IsVisible())
+    {
+        Dialog* pParentDlg = GetParentDialog();
+        pParentDlg->InvalidateFloatingWindow(mpImplData->maPos);
+    }
+    else if (!IsVisible())
+    {
+        Dialog* pParentDlg = GetParentDialog();
+        pParentDlg->CloseFloatingWindow();
+    }
+
     if ( nType == StateChangedType::ControlBackground )
     {
         ImplInitSettings();
@@ -667,8 +679,8 @@ void FloatingWindow::StartPopupMode( const tools::Rectangle& rRect, FloatWinPopu
 
     // compute window position according to flags and arrangement
     sal_uInt16 nArrangeIndex;
-    Point aPos = ImplCalcPos( this, rRect, nFlags, nArrangeIndex );
-    SetPosPixel( aPos );
+    mpImplData->maPos = ImplCalcPos( this, rRect, nFlags, nArrangeIndex );
+    SetPosPixel( mpImplData->maPos );
 
     // set data and display window
     // convert maFloatRect to absolute device coordinates
@@ -714,10 +726,10 @@ void FloatingWindow::StartPopupMode( ToolBox* pBox, FloatWinPopupFlags nFlags )
 
     // retrieve some data from the ToolBox
     tools::Rectangle aRect = nItemId ? pBox->GetItemRect( nItemId ) : pBox->GetOverflowRect();
-    Point aPos;
+
     // convert to parent's screen coordinates
-    aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
-    aRect.SetPos( aPos );
+    mpImplData->maPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
+    aRect.SetPos( mpImplData->maPos );
 
     nFlags |=
         FloatWinPopupFlags::AllMouseButtonClose |
commit 565fcf36297b0a633454b7f3ca8dc383c3f38e46
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Thu Aug 3 14:42:21 2017 +0530

    lokdialog: Register IDIalogRenderable with vcl::Dialog
    
    Change-Id: I344f5a9c7167abfde15dcd21c747819cc79b12b1

diff --git a/include/sfx2/basedlgs.hxx b/include/sfx2/basedlgs.hxx
index 7609229db2a6..cb403c78a075 100644
--- a/include/sfx2/basedlgs.hxx
+++ b/include/sfx2/basedlgs.hxx
@@ -105,8 +105,6 @@ public:
     SfxBindings&            GetBindings()
                             { return *pBindings; }
 
-    virtual void            LogicInvalidate(const tools::Rectangle* pRectangle) override;
-
     DECL_LINK(TimerHdl, Timer *, void);
 
 };
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index cf9d41e54cde..b2c0dee552cd 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -38,6 +38,9 @@ public:
 
     virtual void postDialogMouseEvent(const DialogID& rDialogID, int nType, int nX, int nY,
                                       int nCount, int nButtons, int nModifier) = 0;
+
+    // Callbacks
+    virtual void notifyDialogInvalidation(const DialogID& rDialogID) = 0;
 };
 
 } // namespace vcl
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index f0425a961cf3..e0e3bba35b27 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -25,7 +25,7 @@
 #include <vcl/dllapi.h>
 #include <vcl/syswin.hxx>
 #include <vcl/vclptr.hxx>
-
+#include <vcl/IDialogRenderable.hxx>
 
 struct DialogImpl;
 class VclBox;
@@ -49,6 +49,8 @@ private:
     VclPtr<VclButtonBox> mpActionArea;
     VclPtr<VclBox>       mpContentArea;
 
+    vcl::IDialogRenderable*   mpDialogRenderable; // to emit LOK callbacks
+
     SAL_DLLPRIVATE void    ImplInitDialogData();
     SAL_DLLPRIVATE void    ImplInitSettings();
 
@@ -67,7 +69,10 @@ protected:
 public:
     SAL_DLLPRIVATE bool    IsInClose() const { return mbInClose; }
     virtual        void    doDeferredInit(WinBits nBits) override;
-    virtual        void    LogicInvalidate(const tools::Rectangle* pRectangle) override { (void)pRectangle; }
+    virtual        void    LogicInvalidate(const tools::Rectangle* pRectangle) override;
+
+    /// Necessary to register dialog renderable instance to emit LOK callbacks
+    void registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable);
     /// Paints the current dialog to the given virtual device
     void paintDialog(VirtualDevice& rDevice);
     void LogicMouseButtonDown(const MouseEvent& rMouseEvent);
diff --git a/sfx2/source/dialog/basedlgs.cxx b/sfx2/source/dialog/basedlgs.cxx
index d140c571ab62..8862b0795e92 100644
--- a/sfx2/source/dialog/basedlgs.cxx
+++ b/sfx2/source/dialog/basedlgs.cxx
@@ -393,14 +393,6 @@ void SfxModelessDialog::FillInfo(SfxChildWinInfo& rInfo) const
         rInfo.nFlags |= SfxChildWindowFlags::ZOOMIN;
 }
 
-
-void SfxModelessDialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
-{
-    if (!comphelper::LibreOfficeKit::isDialogPainting())
-        SfxLokHelper::notifyDialogInvalidation(maID);
-}
-
-
 bool SfxFloatingWindow::EventNotify( NotifyEvent& rEvt )
 
 /*  [Description]
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index 330ead910606..c1f575bbee86 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -433,6 +433,8 @@ public:
     void postDialogMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
                               int nCount, int nButtons, int nModifier) override;
 
+    void notifyDialogInvalidation(const vcl::DialogID& rDialogID) 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 3be26d0f28b6..c277ce3153dd 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -31,6 +31,7 @@
 #include <vcl/svapp.hxx>
 #include <vcl/print.hxx>
 #include <sfx2/viewfrm.hxx>
+#include <sfx2/lokhelper.hxx>
 #include <sfx2/sfxbasecontroller.hxx>
 #include <sfx2/docfile.hxx>
 #include <sfx2/msg.hxx>
@@ -3575,6 +3576,8 @@ 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->paintDialog(rDevice);
     const Size aSize = pDlg->GetOptimalSize();
     nWidth = aSize.getWidth();
@@ -3654,6 +3657,11 @@ void SwXTextDocument::postDialogMouseEvent(const vcl::DialogID& rDialogID, int n
     }
 }
 
+void SwXTextDocument::notifyDialogInvalidation(const vcl::DialogID& rDialogID)
+{
+    SfxLokHelper::notifyDialogInvalidation(rDialogID);
+}
+
 void * SAL_CALL SwXTextDocument::operator new( size_t t) throw()
 {
     return SwXTextDocumentBaseClass::operator new(t);
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 897bc8f74543..65bb09305752 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -348,6 +348,7 @@ struct DialogImpl
 
 void Dialog::ImplInitDialogData()
 {
+    mpDialogRenderable = nullptr;
     mpWindowImpl->mbDialog  = true;
     mpPrevExecuteDlg        = nullptr;
     mbInExecute             = false;
@@ -853,6 +854,14 @@ bool Dialog::selectPageByUIXMLDescription(const OString& /*rUIXMLDescription*/)
     return true;
 }
 
+void Dialog::registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable)
+{
+    if (pDialogRenderable && !mpDialogRenderable)
+    {
+        mpDialogRenderable = pDialogRenderable;
+    }
+}
+
 void Dialog::paintDialog(VirtualDevice& rDevice)
 {
     setDeferredProperties();
@@ -864,6 +873,14 @@ void Dialog::paintDialog(VirtualDevice& rDevice)
     PaintToDevice(&rDevice, Point(0, 0), Size());
 }
 
+void Dialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+{
+    if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable && !maID.isEmpty())
+    {
+        mpDialogRenderable->notifyDialogInvalidation(maID);
+    }
+}
+
 void Dialog::LogicMouseButtonDown(const MouseEvent& rMouseEvent)
 {
     // When we're not doing tiled rendering, then positions must be passed as pixels.
commit 867312490af7461e1892ecb1184d9c48d8e4a96a
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Wed Aug 2 18:01:45 2017 +0530

    Fix a comment
    
    Change-Id: Icbd16aebf3ddabd1b0ffd310f1aab3641d5c40b4

diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index 65cd5964af97..b37480df9da1 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -40,7 +40,7 @@ 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 const* pOtherView, int nType, const OString& rKey, const OString& rPayload);
-    /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.
+    /// Emits a LOK_CALLBACK_DIALOG_INVALIDATE
     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);


More information about the Libreoffice-commits mailing list