desktop/source/lib/init.cxx            |    5 +
 include/sfx2/lokcomponenthelpers.hxx   |    2 
 sfx2/source/view/lokstarmathhelper.cxx |   23 ++++++--
 starmath/inc/cursor.hxx                |    2 
 starmath/inc/view.hxx                  |    9 +--
 starmath/inc/visitors.hxx              |   60 +++++++++++++++++----
 starmath/source/cursor.cxx             |   14 ++++-
 starmath/source/view.cxx               |   56 +++++++++++++++++++-
 starmath/source/visitors.cxx           |   91 ++++++++++++++++++++-------------
 9 files changed, 205 insertions(+), 57 deletions(-)

New commits:
commit 14ed342dd3f4cae607f7785905787f73c7b1fde2
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Nov 2 11:03:08 2022 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Nov 5 09:19:07 2022 +0100

    lok: show Math cursor
    
    Change-Id: I17a449f0a0662f0433de9cad1522a090434c1e30
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142178
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 46dbe3e5d9c6..6414a3fe1ca9 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -2138,6 +2138,11 @@ void CallbackFlushHandler::enqueueUpdatedTypes()
 
 void CallbackFlushHandler::enqueueUpdatedType( int type, const SfxViewShell* 
viewShell, int viewId )
 {
+    if (type == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR)
+    {
+        if (const SfxViewShell* viewShell2 = 
LokStarMathHelper(viewShell).GetSmViewShell())
+            viewShell = viewShell2;
+    }
     std::optional<OString> payload = viewShell->getLOKPayload( type, viewId );
     if(!payload)
         return; // No actual payload to send.
diff --git a/include/sfx2/lokcomponenthelpers.hxx 
b/include/sfx2/lokcomponenthelpers.hxx
index b26cd0a13fb8..23bdcd44369e 100644
--- a/include/sfx2/lokcomponenthelpers.hxx
+++ b/include/sfx2/lokcomponenthelpers.hxx
@@ -72,6 +72,8 @@ public:
 
     vcl::Window* GetGraphicWindow();
     vcl::Window* GetWidgetWindow();
+    const SfxViewShell* GetSmViewShell();
+    tools::Rectangle GetBoundingBox() const;
 
     void Dispatch(const OUString& cmd, const 
css::uno::Sequence<css::beans::PropertyValue>& rArguments) const;
 
diff --git a/sfx2/source/view/lokstarmathhelper.cxx 
b/sfx2/source/view/lokstarmathhelper.cxx
index fb30d9cee449..8ec65c45a274 100644
--- a/sfx2/source/view/lokstarmathhelper.cxx
+++ b/sfx2/source/view/lokstarmathhelper.cxx
@@ -122,14 +122,29 @@ vcl::Window* LokStarMathHelper::GetWidgetWindow()
     return mpWidgetWindow.get();
 }
 
+const SfxViewShell* LokStarMathHelper::GetSmViewShell()
+{
+    if (vcl::Window* pGraphWindow = GetGraphicWindow())
+    {
+        return SfxViewShell::GetFirst(false, [pGraphWindow](const 
SfxViewShell* shell) {
+            return shell->GetWindow() && 
shell->GetWindow()->IsChild(pGraphWindow);
+        });
+    }
+    return nullptr;
+}
+
+tools::Rectangle LokStarMathHelper::GetBoundingBox() const
+{
+    return mpIPClient ? mpIPClient->GetObjArea() : tools::Rectangle{};
+}
+
 bool LokStarMathHelper::postMouseEvent(int nType, int nX, int nY, int nCount, 
int nButtons,
                                        int nModifier, double /*fScaleX*/, 
double /*fScaleY*/)
 {
-    if (vcl::Window* pWindow = GetWidgetWindow())
+    const tools::Rectangle rBBox = GetBoundingBox();
+    if (Point aMousePos(nX, nY); rBBox.Contains(aMousePos))
     {
-        Point aMousePos(nX, nY);
-        tools::Rectangle rBBox = mpIPClient->GetObjArea();
-        if (rBBox.Contains(aMousePos))
+        if (vcl::Window* pWindow = GetWidgetWindow())
         {
             aMousePos -= rBBox.TopLeft();
             LokMouseEventData aMouseEventData(
diff --git a/starmath/inc/cursor.hxx b/starmath/inc/cursor.hxx
index 5886ffaf2eac..a1491c5decfe 100644
--- a/starmath/inc/cursor.hxx
+++ b/starmath/inc/cursor.hxx
@@ -186,6 +186,8 @@ public:
     /** Draw the caret */
     void Draw(OutputDevice& pDev, Point Offset, bool isCaretVisible);
 
+    tools::Rectangle GetCaretRectangle(OutputDevice& rOutDev) const;
+
     bool IsAtTailOfBracket(SmBracketType eBracketType) const;
 
 private:
diff --git a/starmath/inc/view.hxx b/starmath/inc/view.hxx
index 309c89513489..1905edb02741 100644
--- a/starmath/inc/view.hxx
+++ b/starmath/inc/view.hxx
@@ -136,10 +136,7 @@ public:
     }
 
 private:
-    void SetIsCursorVisible(bool bVis)
-    {
-        bIsCursorVisible = bVis;
-    }
+    void SetIsCursorVisible(bool bVis);
     void SetCursor(const SmNode *pNode);
     void SetCursor(const tools::Rectangle &rRect);
 
@@ -295,7 +292,7 @@ public:
     SmViewShell(SfxViewFrame *pFrame, SfxViewShell *pOldSh);
     virtual ~SmViewShell() override;
 
-    SmDocShell * GetDoc()
+    SmDocShell * GetDoc() const
     {
         return static_cast<SmDocShell *>( GetViewFrame()->GetObjectShell() );
     }
@@ -325,6 +322,8 @@ public:
     SFX_DECL_INTERFACE(SFX_INTERFACE_SMA_START+SfxInterfaceId(2))
     SFX_DECL_VIEWFACTORY(SmViewShell);
 
+    void SendCaretToLOK() const;
+
 private:
     /// SfxInterface initializer.
     static void InitInterface_Impl();
diff --git a/starmath/inc/visitors.hxx b/starmath/inc/visitors.hxx
index 27c4e374e9ff..b29bb26fb5b0 100644
--- a/starmath/inc/visitors.hxx
+++ b/starmath/inc/visitors.hxx
@@ -111,26 +111,64 @@ protected:
     virtual void DefaultVisit( SmNode* pNode ) = 0;
 };
 
-// SmCaretDrawingVisitor
+// SmCaretLinesVisitor: ancestor of caret rectangle enumeration and drawing 
visitors
 
-/** Visitor for drawing a caret position */
-class SmCaretDrawingVisitor final : public SmDefaultingVisitor
+class SmCaretLinesVisitor : public SmDefaultingVisitor
 {
 public:
-    /** Given position and device this constructor will draw the caret */
-    SmCaretDrawingVisitor( OutputDevice& rDevice, SmCaretPos position, Point 
offset, bool caretVisible );
-    virtual ~SmCaretDrawingVisitor() {}
-    void Visit( SmTextNode* pNode ) override;
+    SmCaretLinesVisitor(OutputDevice& rDevice, SmCaretPos position, Point 
offset);
+    virtual ~SmCaretLinesVisitor() = default;
+    void Visit(SmTextNode* pNode) override;
     using SmDefaultingVisitor::Visit;
+
+protected:
+    void DoIt();
+
+    OutputDevice& getDev() { return mrDev; }
+    virtual void ProcessCaretLine(Point from, Point to) = 0;
+    virtual void ProcessUnderline(Point from, Point to) = 0;
+
+    /** Default method for drawing pNodes */
+    void DefaultVisit(SmNode* pNode) override;
+
 private:
-    OutputDevice &mrDev;
+    OutputDevice& mrDev;
     SmCaretPos maPos;
     /** Offset to draw from */
     Point  maOffset;
-    bool  mbCaretVisible;
+};
 
-    /** Default method for drawing pNodes */
-    void DefaultVisit( SmNode* pNode ) override;
+// SmCaretRectanglesVisitor: obtains the set of rectangles to sent to lok
+
+class SmCaretRectanglesVisitor final : public SmCaretLinesVisitor
+{
+public:
+    SmCaretRectanglesVisitor(OutputDevice& rDevice, SmCaretPos position);
+    const tools::Rectangle& getCaret() const { return maCaret; }
+
+protected:
+    virtual void ProcessCaretLine(Point from, Point to) override;
+    virtual void ProcessUnderline(Point from, Point to) override;
+
+private:
+    tools::Rectangle maCaret;
+};
+
+// SmCaretDrawingVisitor
+
+/** Visitor for drawing a caret position */
+class SmCaretDrawingVisitor final : public SmCaretLinesVisitor
+{
+public:
+    /** Given position and device this constructor will draw the caret */
+    SmCaretDrawingVisitor( OutputDevice& rDevice, SmCaretPos position, Point 
offset, bool caretVisible );
+
+protected:
+    virtual void ProcessCaretLine(Point from, Point to) override;
+    virtual void ProcessUnderline(Point from, Point to) override;
+
+private:
+    bool  mbCaretVisible;
 };
 
 // SmCaretPos2LineVisitor
diff --git a/starmath/source/cursor.cxx b/starmath/source/cursor.cxx
index fc1e3c5ecb7b..f6d93b8f11cf 100644
--- a/starmath/source/cursor.cxx
+++ b/starmath/source/cursor.cxx
@@ -11,8 +11,11 @@
 #include <document.hxx>
 #include <view.hxx>
 #include <comphelper/string.hxx>
+#include <comphelper/lok.hxx>
 #include <editeng/editeng.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <osl/diagnose.h>
+#include <sfx2/lokhelper.hxx>
 
 void SmCursor::Move(OutputDevice* pDev, SmMovementDirection direction, bool 
bMoveAnchor){
     SmCaretPosGraphEntry* NewPos = nullptr;
@@ -171,6 +174,11 @@ void SmCursor::Draw(OutputDevice& pDev, Point Offset, bool 
isCaretVisible){
     SmCaretDrawingVisitor(pDev, GetPosition(), Offset, isCaretVisible);
 }
 
+tools::Rectangle SmCursor::GetCaretRectangle(OutputDevice& rOutDev) const
+{
+    return SmCaretRectanglesVisitor(rOutDev, GetPosition()).getCaret();
+}
+
 void SmCursor::DeletePrev(OutputDevice* pDev){
     //Delete only a selection if there's a selection
     if(HasSelection()){
@@ -1319,7 +1327,11 @@ void SmCursor::EndEdit(){
 void SmCursor::RequestRepaint(){
     SmViewShell *pViewSh = SmGetActiveView();
     if( pViewSh ) {
-        if ( SfxObjectCreateMode::EMBEDDED == mpDocShell->GetCreateMode() )
+        if (comphelper::LibreOfficeKit::isActive())
+        {
+            pViewSh->SendCaretToLOK();
+        }
+        else if ( SfxObjectCreateMode::EMBEDDED == mpDocShell->GetCreateMode() 
)
             mpDocShell->Repaint();
         else
             pViewSh->GetGraphicWidget().Invalidate();
diff --git a/starmath/source/view.cxx b/starmath/source/view.cxx
index aee745931ee7..95a175081737 100644
--- a/starmath/source/view.cxx
+++ b/starmath/source/view.cxx
@@ -40,6 +40,8 @@
 #include <sfx2/docinsert.hxx>
 #include <sfx2/filedlghelper.hxx>
 #include <sfx2/infobar.hxx>
+#include <sfx2/lokcomponenthelpers.hxx>
+#include <sfx2/lokhelper.hxx>
 #include <sfx2/msg.hxx>
 #include <sfx2/objface.hxx>
 #include <sfx2/printer.hxx>
@@ -365,6 +367,9 @@ bool SmGraphicWidget::MouseButtonDown(const MouseEvent& 
rMEvt)
 
     if (SmViewShell::IsInlineEditEnabled()) {
         GetCursor().MoveTo(&rDevice, aPos, !rMEvt.IsShift());
+        // 'on grab' window events are missing in lok, do it explicitly
+        if (comphelper::LibreOfficeKit::isActive())
+            SetIsCursorVisible(true);
         return true;
     }
     const SmNode *pNode = nullptr;
@@ -456,13 +461,15 @@ IMPL_LINK_NOARG(SmGraphicWidget, CaretBlinkTimerHdl, 
Timer *, void)
 
 void SmGraphicWidget::CaretBlinkInit()
 {
+    if (comphelper::LibreOfficeKit::isActive())
+        return; // No blinking in lok case
     aCaretBlinkTimer.SetInvokeHandler(LINK(this, SmGraphicWidget, 
CaretBlinkTimerHdl));
     
aCaretBlinkTimer.SetTimeout(Application::GetSettings().GetStyleSettings().GetCursorBlinkTime());
 }
 
 void SmGraphicWidget::CaretBlinkStart()
 {
-    if (!SmViewShell::IsInlineEditEnabled())
+    if (!SmViewShell::IsInlineEditEnabled() || 
comphelper::LibreOfficeKit::isActive())
         return;
     if (aCaretBlinkTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME)
         aCaretBlinkTimer.Start();
@@ -470,7 +477,7 @@ void SmGraphicWidget::CaretBlinkStart()
 
 void SmGraphicWidget::CaretBlinkStop()
 {
-    if (!SmViewShell::IsInlineEditEnabled())
+    if (!SmViewShell::IsInlineEditEnabled() || 
comphelper::LibreOfficeKit::isActive())
         return;
     aCaretBlinkTimer.Stop();
 }
@@ -496,6 +503,17 @@ void SmGraphicWidget::ShowLine(bool bShow)
     bIsLineVisible = bShow;
 }
 
+void SmGraphicWidget::SetIsCursorVisible(bool bVis)
+{
+    bIsCursorVisible = bVis;
+    if (comphelper::LibreOfficeKit::isActive())
+    {
+        mrViewShell.SendCaretToLOK();
+        mrViewShell.libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE,
+                                               
OString::boolean(bVis).getStr());
+    }
+}
+
 void SmGraphicWidget::SetCursor(const SmNode *pNode)
 {
     if (SmViewShell::IsInlineEditEnabled())
@@ -2131,6 +2149,16 @@ public:
         mpSelectionChangeHandler->selectionChanged({}); // Installs the 
correct context
     }
 
+    virtual void SAL_CALL dispose() override
+    {
+        if (comphelper::LibreOfficeKit::isActive())
+            if (auto pViewShell = GetViewShell_Impl())
+                
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE,
+                                                       
OString::boolean(false).getStr());
+
+        SfxBaseController::dispose();
+    }
+
 private:
     static OUString GetContextName() { return "Math"; } // Static constant for 
now
 
@@ -2282,6 +2310,20 @@ std::optional<OString> SmViewShell::getLOKPayload(int 
nType, int nViewId) const
     switch (nType)
     {
         case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
+        {
+            OString sRectangle;
+            if (const SmGraphicWidget& widget = GetGraphicWidget(); 
widget.IsCursorVisible())
+            {
+                SmCursor& rCursor = GetDoc()->GetCursor();
+                OutputDevice& rOutDev = 
const_cast<SmGraphicWidget&>(widget).GetOutputDevice();
+                tools::Rectangle aCaret = rCursor.GetCaretRectangle(rOutDev);
+                LokStarMathHelper helper(SfxViewShell::Current());
+                tools::Rectangle aBounds = helper.GetBoundingBox();
+                aCaret.Move(aBounds.Left(), aBounds.Top());
+                sRectangle = aCaret.toString();
+            }
+            return SfxLokHelper::makeVisCursorInvalidation(nViewId, 
sRectangle, false, {});
+        }
         case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
         case LOK_CALLBACK_TEXT_SELECTION:
         case LOK_CALLBACK_TEXT_SELECTION_START:
@@ -2292,4 +2334,14 @@ std::optional<OString> SmViewShell::getLOKPayload(int 
nType, int nViewId) const
     return SfxViewShell::getLOKPayload(nType, nViewId); // aborts
 }
 
+void SmViewShell::SendCaretToLOK() const
+{
+    const int nViewId = sal_Int32(GetViewShellId());
+    if (const auto& payload = 
getLOKPayload(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, nViewId))
+    {
+        
libreOfficeKitViewCallbackWithViewId(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR,
+                                             payload->getStr(), nViewId);
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/starmath/source/visitors.cxx b/starmath/source/visitors.cxx
index 980c6346ca80..fdf268b65960 100644
--- a/starmath/source/visitors.cxx
+++ b/starmath/source/visitors.cxx
@@ -154,19 +154,19 @@ void SmDefaultingVisitor::Visit( SmVerticalBraceNode* 
pNode )
     DefaultVisit( pNode );
 }
 
-// SmCaretDrawingVisitor
+// SmCaretLinesVisitor
 
-SmCaretDrawingVisitor::SmCaretDrawingVisitor( OutputDevice& rDevice,
-                                             SmCaretPos position,
-                                             Point offset,
-                                             bool caretVisible )
-    : mrDev( rDevice )
-    , maPos( position )
-    , maOffset( offset )
-    , mbCaretVisible( caretVisible )
+SmCaretLinesVisitor::SmCaretLinesVisitor(OutputDevice& rDevice, SmCaretPos 
position, Point offset)
+    : mrDev(rDevice)
+    , maPos(position)
+    , maOffset(offset)
+{
+}
+
+void SmCaretLinesVisitor::DoIt()
 {
-    SAL_WARN_IF( !position.IsValid(), "starmath", "Cannot draw invalid 
position!" );
-    if( !position.IsValid( ) )
+    SAL_WARN_IF(!maPos.IsValid(), "starmath", "Cannot draw invalid position!");
+    if (!maPos.IsValid())
         return;
 
     //Save device state
@@ -177,7 +177,7 @@ SmCaretDrawingVisitor::SmCaretDrawingVisitor( OutputDevice& 
rDevice,
     mrDev.Pop( );
 }
 
-void SmCaretDrawingVisitor::Visit( SmTextNode* pNode )
+void SmCaretLinesVisitor::Visit( SmTextNode* pNode )
 {
     tools::Long i = maPos.nIndex;
 
@@ -193,23 +193,14 @@ void SmCaretDrawingVisitor::Visit( SmTextNode* pNode )
     tools::Long left_line = pLine->GetLeft( ) + maOffset.X( );
     tools::Long right_line = pLine->GetRight( ) + maOffset.X( );
 
-    //Set color
-    mrDev.SetLineColor( COL_BLACK );
-
-    if ( mbCaretVisible ) {
-        //Draw vertical line
-        Point p1( left, top );
-        Point p2( left, top + height );
-        mrDev.DrawLine( p1, p2 );
-    }
+    // Vertical line
+    ProcessCaretLine({ left, top }, { left, top + height });
 
-    //Underline the line
-    Point aLeft( left_line, top + height );
-    Point aRight( right_line, top + height );
-    mrDev.DrawLine( aLeft, aRight );
+    // Underline
+    ProcessUnderline({ left_line, top + height }, { right_line, top + height 
});
 }
 
-void SmCaretDrawingVisitor::DefaultVisit( SmNode* pNode )
+void SmCaretLinesVisitor::DefaultVisit( SmNode* pNode )
 {
     //Find the line
     SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode );
@@ -221,20 +212,52 @@ void SmCaretDrawingVisitor::DefaultVisit( SmNode* pNode )
     tools::Long left_line = pLine->GetLeft( ) + maOffset.X( );
     tools::Long right_line = pLine->GetRight( ) + maOffset.X( );
 
-    //Set color
-    mrDev.SetLineColor( COL_BLACK );
+    // Vertical line
+    ProcessCaretLine({ left, top }, { left, top + height });
+
+    // Underline
+    ProcessUnderline({ left_line, top + height }, { right_line, top + height 
});
+}
 
+// SmCaretRectanglesVisitor
+
+SmCaretRectanglesVisitor::SmCaretRectanglesVisitor(OutputDevice& rDevice, 
SmCaretPos position)
+    : SmCaretLinesVisitor(rDevice, position, {})
+{
+    DoIt();
+}
+
+void SmCaretRectanglesVisitor::ProcessCaretLine(Point from, Point to) { 
maCaret = { from, to }; }
+void SmCaretRectanglesVisitor::ProcessUnderline(Point /*from*/, Point /*to*/) 
{} // No underline
+
+// SmCaretDrawingVisitor
+
+SmCaretDrawingVisitor::SmCaretDrawingVisitor( OutputDevice& rDevice,
+                                             SmCaretPos position,
+                                             Point offset,
+                                             bool caretVisible )
+    : SmCaretLinesVisitor(rDevice, position, offset)
+    , mbCaretVisible( caretVisible )
+{
+    DoIt();
+}
+
+void SmCaretDrawingVisitor::ProcessCaretLine(Point from, Point to)
+{
     if ( mbCaretVisible ) {
+        //Set color
+        getDev().SetLineColor(COL_BLACK);
         //Draw vertical line
-        Point p1( left, top );
-        Point p2( left, top + height );
-        mrDev.DrawLine( p1, p2 );
+        getDev().DrawLine(from, to);
     }
+}
 
+void SmCaretDrawingVisitor::ProcessUnderline(Point from, Point to)
+{
+    //Set color
+    getDev().SetLineColor(COL_BLACK);
     //Underline the line
-    Point aLeft( left_line, top + height );
-    Point aRight( right_line, top + height );
-    mrDev.DrawLine( aLeft, aRight );
+    getDev().DrawLine(from, to);
 }
 
 // SmCaretPos2LineVisitor

Reply via email to