summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--editeng/source/editeng/editview.cxx10
-rw-r--r--editeng/source/editeng/impedit.cxx99
-rw-r--r--editeng/source/editeng/impedit.hxx10
-rw-r--r--include/editeng/editview.hxx2
-rw-r--r--sc/source/ui/inc/gridwin.hxx15
-rw-r--r--sc/source/ui/view/gridwin4.cxx125
-rw-r--r--sc/source/ui/view/viewdata.cxx1
7 files changed, 224 insertions, 38 deletions
diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx
index 531fad3e12c2..34509b4d4e74 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -470,6 +470,16 @@ void EditView::Command( const CommandEvent& rCEvt )
pImpEditView->Command( rCEvt );
}
+void EditView::SetBroadcastLOKViewCursor(bool bSet)
+{
+ pImpEditView->SetBroadcastLOKViewCursor(bSet);
+}
+
+tools::Rectangle EditView::GetEditCursor() const
+{
+ return pImpEditView->GetEditCursor();
+}
+
void EditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor, bool bActivate )
{
if ( !pImpEditView->pEditEngine->HasView( this ) )
diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx
index e0ee7a52b24d..b5be152d6ece 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -81,7 +81,8 @@ ImpEditView::ImpEditView( EditView* pView, EditEngine* pEng, vcl::Window* pWindo
aOutArea( Point(), pEng->GetPaperSize() ),
eSelectionMode(EESelectionMode::Std),
eAnchorMode(EEAnchorMode::TopLeft),
- mpEditViewCallbacks(nullptr)
+ mpEditViewCallbacks(nullptr),
+ mbBroadcastLOKViewCursor(comphelper::LibreOfficeKit::isActive())
{
aEditSelection.Min() = pEng->GetEditDoc().GetStartPaM();
aEditSelection.Max() = pEng->GetEditDoc().GetEndPaM();
@@ -913,6 +914,69 @@ OString buildHyperlinkJSON(const OUString& sText, const OUString& sLink)
} // End of anon namespace
+tools::Rectangle ImpEditView::ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nShowCursorFlags, sal_Int32& nTextPortionStart,
+ const ParaPortion* pParaPortion) const
+{
+ tools::Rectangle aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, nShowCursorFlags );
+ if ( !IsInsertMode() && !aEditSelection.HasRange() )
+ {
+ if ( aPaM.GetNode()->Len() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) )
+ {
+ // If we are behind a portion, and the next portion has other direction, we must change position...
+ aEditCursor.SetLeft( pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GetCursorFlags::TextOnly|GetCursorFlags::PreferPortionStart ).Left() );
+ aEditCursor.SetRight( aEditCursor.Left() );
+
+ sal_Int32 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, true );
+ const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[nTextPortion];
+ if ( rTextPortion.GetKind() == PortionKind::TAB )
+ {
+ aEditCursor.AdjustRight(rTextPortion.GetSize().Width() );
+ }
+ else
+ {
+ EditPaM aNext = pEditEngine->CursorRight( aPaM );
+ tools::Rectangle aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly );
+ if ( aTmpRect.Top() != aEditCursor.Top() )
+ aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly|GetCursorFlags::EndOfLine );
+ aEditCursor.SetRight( aTmpRect.Left() );
+ }
+ }
+ }
+
+ long nMaxHeight = !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth();
+ if ( aEditCursor.GetHeight() > nMaxHeight )
+ {
+ aEditCursor.SetBottom( aEditCursor.Top() + nMaxHeight - 1 );
+ }
+
+ return aEditCursor;
+}
+
+tools::Rectangle ImpEditView::GetEditCursor() const
+{
+ EditPaM aPaM( aEditSelection.Max() );
+
+ sal_Int32 nTextPortionStart = 0;
+ sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
+ if (nPara == EE_PARA_NOT_FOUND) // #i94322
+ return tools::Rectangle();
+
+ const ParaPortion* pParaPortion = pEditEngine->GetParaPortions()[nPara];
+
+ GetCursorFlags nShowCursorFlags = nExtraCursorFlags | GetCursorFlags::TextOnly;
+
+ // Use CursorBidiLevel 0/1 in meaning of
+ // 0: prefer portion end, normal mode
+ // 1: prefer portion start
+
+ if ( ( GetCursorBidiLevel() != CURSOR_BIDILEVEL_DONTKNOW ) && GetCursorBidiLevel() )
+ {
+ nShowCursorFlags |= GetCursorFlags::PreferPortionStart;
+ }
+
+ return ImplGetEditCursor(aPaM, nShowCursorFlags, nTextPortionStart, pParaPortion);
+}
+
void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor )
{
// No ShowCursor in an empty View ...
@@ -957,36 +1021,8 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor )
nShowCursorFlags |= GetCursorFlags::PreferPortionStart;
}
- tools::Rectangle aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, nShowCursorFlags );
- if ( !IsInsertMode() && !aEditSelection.HasRange() )
- {
- if ( aPaM.GetNode()->Len() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) )
- {
- // If we are behind a portion, and the next portion has other direction, we must change position...
- aEditCursor.SetLeft( pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GetCursorFlags::TextOnly|GetCursorFlags::PreferPortionStart ).Left() );
- aEditCursor.SetRight( aEditCursor.Left() );
+ tools::Rectangle aEditCursor = ImplGetEditCursor(aPaM, nShowCursorFlags, nTextPortionStart, pParaPortion);
- sal_Int32 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, true );
- const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[nTextPortion];
- if ( rTextPortion.GetKind() == PortionKind::TAB )
- {
- aEditCursor.AdjustRight(rTextPortion.GetSize().Width() );
- }
- else
- {
- EditPaM aNext = pEditEngine->CursorRight( aPaM );
- tools::Rectangle aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly );
- if ( aTmpRect.Top() != aEditCursor.Top() )
- aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly|GetCursorFlags::EndOfLine );
- aEditCursor.SetRight( aTmpRect.Left() );
- }
- }
- }
- long nMaxHeight = !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth();
- if ( aEditCursor.GetHeight() > nMaxHeight )
- {
- aEditCursor.SetBottom( aEditCursor.Top() + nMaxHeight - 1 );
- }
if ( bGotoCursor ) // && (!pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() ) )
{
// check if scrolling is necessary...
@@ -1177,7 +1213,8 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor )
}
SfxLokHelper::notifyVisCursorInvalidation(mpViewShell, sRect, bIsWrong, sHyperlink);
- mpViewShell->NotifyOtherViews(LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect);
+ if (mbBroadcastLOKViewCursor)
+ mpViewShell->NotifyOtherViews(LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect);
}
}
diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
index 0eaf70f5ae26..bf6196953ea6 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -262,6 +262,7 @@ private:
// in Draw/Impress in an OverlayObject which avoids evtl. expensive full
// repaints of the EditView(s)
const EditViewCallbacks* mpEditViewCallbacks;
+ bool mbBroadcastLOKViewCursor;
const EditViewCallbacks* getEditViewCallbacks() const
{
@@ -278,6 +279,11 @@ private:
css::uno::Reference<css::datatransfer::clipboard::XClipboard> GetClipboard() const;
css::uno::Reference<css::datatransfer::clipboard::XClipboard> GetSelection() const;
+ void SetBroadcastLOKViewCursor(bool bSet)
+ {
+ mbBroadcastLOKViewCursor = bSet;
+ }
+
protected:
// DragAndDropClient
@@ -292,6 +298,8 @@ protected:
void HideDDCursor();
void ImplDrawHighlightRect( OutputDevice* _pTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly );
+ tools::Rectangle ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nShowCursorFlags,
+ sal_Int32& nTextPortionStart, const ParaPortion* pParaPortion) const;
public:
ImpEditView( EditView* pView, EditEngine* pEng, vcl::Window* pWindow );
@@ -370,6 +378,8 @@ public:
void CalcAnchorPoint();
void RecalcOutputArea();
+ tools::Rectangle GetEditCursor() const;
+
void ShowCursor( bool bGotoCursor, bool bForceVisCursor );
Pair Scroll( long ndX, long ndY, ScrollRangeCheck nRangeCheck = ScrollRangeCheck::NoNegative );
diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx
index 0f76948c3ffc..441dcb99c794 100644
--- a/include/editeng/editview.hxx
+++ b/include/editeng/editview.hxx
@@ -160,6 +160,8 @@ public:
void Invalidate();
Pair Scroll( long nHorzScroll, long nVertScroll, ScrollRangeCheck nRangeCheck = ScrollRangeCheck::NoNegative );
+ void SetBroadcastLOKViewCursor(bool bSet);
+ tools::Rectangle GetEditCursor() const;
void ShowCursor( bool bGotoCursor = true, bool bForceVisCursor = true, bool bActivate = false );
void HideCursor( bool bDeactivate = false );
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 6369e5fcf159..e712e3dcf634 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -131,6 +131,17 @@ class SAL_DLLPUBLIC_RTTI ScGridWindow : public vcl::Window, public DropTargetHel
VisibleRange maVisibleRange;
+ struct LOKCursorEntry
+ {
+ Fraction aScaleX;
+ Fraction aScaleY;
+ tools::Rectangle aRect;
+ };
+
+ // Stores the last cursor position in twips for all
+ // zoom levels demanded from a ScGridWindow instance.
+ std::vector<LOKCursorEntry> maLOKLastCursor;
+
std::unique_ptr<sc::SpellCheckContext> mpSpellCheckCxt;
ScViewData* pViewData;
@@ -291,6 +302,10 @@ class SAL_DLLPUBLIC_RTTI ScGridWindow : public vcl::Window, public DropTargetHel
::std::vector< tools::Rectangle >& rPixelRects ) const;
void UpdateKitSelection(const std::vector<tools::Rectangle>& rRectangles,
std::vector<tools::Rectangle>* pLogicRects = nullptr);
+ bool NeedLOKCursorInvalidation(const tools::Rectangle& rCursorRect,
+ const Fraction aScaleX, const Fraction aScaleY);
+ void InvalidateLOKViewCursor(const tools::Rectangle& rCursorRect,
+ const Fraction aScaleX, const Fraction aScaleY);
protected:
virtual void PrePaint(vcl::RenderContext& rRenderContext) override;
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 49008ed28f4f..8c60a5c9efc3 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -301,6 +301,59 @@ void ScGridWindow::PrePaint(vcl::RenderContext& /*rRenderContext*/)
}
}
+bool ScGridWindow::NeedLOKCursorInvalidation(const tools::Rectangle& rCursorRect,
+ const Fraction aScaleX, const Fraction aScaleY)
+{
+ // Don't see the need for a map as there will be only a few zoom levels
+ // and as of now X and Y zooms in online are the same.
+ for (auto& rEntry : maLOKLastCursor)
+ {
+ if (aScaleX == rEntry.aScaleX && aScaleY == rEntry.aScaleY)
+ {
+ if (rCursorRect == rEntry.aRect)
+ return false; // No change
+
+ // Update and allow invalidate.
+ rEntry.aRect = rCursorRect;
+ return true;
+ }
+ }
+
+ maLOKLastCursor.push_back(LOKCursorEntry{aScaleX, aScaleY, rCursorRect});
+ return true;
+}
+
+void ScGridWindow::InvalidateLOKViewCursor(const tools::Rectangle& rCursorRect,
+ const Fraction aScaleX, const Fraction aScaleY)
+{
+ if (!NeedLOKCursorInvalidation(rCursorRect, aScaleX, aScaleY))
+ return;
+
+ ScTabViewShell* pThisViewShell = pViewData->GetViewShell();
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+
+ while (pViewShell)
+ {
+ if (pViewShell != pThisViewShell)
+ {
+ ScTabViewShell* pOtherViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
+ if (pOtherViewShell)
+ {
+ ScViewData& rOtherViewData = pOtherViewShell->GetViewData();
+ Fraction aZoomX = rOtherViewData.GetZoomX();
+ Fraction aZoomY = rOtherViewData.GetZoomY();
+ if (aZoomX == aScaleX && aZoomY == aScaleY)
+ {
+ SfxLokHelper::notifyOtherView(pThisViewShell, pOtherViewShell,
+ LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", rCursorRect.toString());
+ }
+ }
+ }
+
+ pViewShell = SfxViewShell::GetNext(*pViewShell);
+ }
+}
+
void ScGridWindow::Paint( vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& rRect )
{
ScDocument* pDoc = pViewData->GetDocument();
@@ -922,13 +975,11 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI
{
long nScreenX = aOutputData.nScrX;
long nScreenY = aOutputData.nScrY;
- long nScreenW = aOutputData.GetScrW();
- long nScreenH = aOutputData.GetScrH();
rDevice.SetLineColor();
rDevice.SetFillColor(pOtherEditView->GetBackgroundColor());
- Point aStart = rOtherViewData.GetScrPos( nCol1, nRow1, eOtherWhich );
- Point aEnd = rOtherViewData.GetScrPos( nCol2+1, nRow2+1, eOtherWhich );
+ Point aStart = pViewData->GetScrPos( nCol1, nRow1, eOtherWhich );
+ Point aEnd = pViewData->GetScrPos( nCol2+1, nRow2+1, eOtherWhich );
// don't overwrite grid
long nLayoutSign = bLayoutRTL ? -1 : 1;
@@ -956,8 +1007,24 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI
// paint the background
rDevice.DrawRect(rDevice.PixelToLogic(aBackground));
- tools::Rectangle aEditRect(Point(nScreenX, nScreenY), Size(nScreenW, nScreenH));
+ tools::Rectangle aEditRect(aBackground);
+ aEditRect.AdjustLeft(1);
+ aEditRect.AdjustTop(1);
+
+ // EditView has an 'output area' which is used to clip the 'paint area' we provide below.
+ // So they need to be in the same coordinates/units. This is tied to the mapmode of the gridwin
+ // attached to the EditView, so we have to change its mapmode too (temporarily). We save the
+ // original mapmode and 'output area' and roll them back when we finish painting to rDevice.
+ vcl::Window* pOtherWin = pOtherEditView->GetWindow();
+ const tools::Rectangle aOrigOutputArea(pOtherEditView->GetOutputArea()); // Not in pixels.
+ const MapMode aOrigMapMode = pOtherWin->GetMapMode();
+ pOtherWin->SetMapMode(rDevice.GetMapMode());
+ pOtherEditView->SetOutputArea(rDevice.PixelToLogic(aEditRect));
pOtherEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice);
+
+ // Rollback the mapmode and 'output area'.
+ pOtherWin->SetMapMode(aOrigMapMode);
+ pOtherEditView->SetOutputArea(aOrigOutputArea);
rDevice.SetMapMode(MapMode(MapUnit::MapPixel));
}
}
@@ -1001,6 +1068,8 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI
// set the correct mapmode
tools::Rectangle aBackground(aStart, aEnd);
+ tools::Rectangle aBGAbs(aStart, aEnd);
+
if (bIsTiledRendering)
{
// Need to draw the background in absolute coords.
@@ -1036,8 +1105,50 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI
rDevice.DrawRect(aLogicRect);
// paint the editeng text
- tools::Rectangle aEditRect(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
- pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice);
+ if (bIsTiledRendering)
+ {
+ tools::Rectangle aEditRect(aBackground);
+ aEditRect.AdjustLeft(1);
+ aEditRect.AdjustTop(1);
+ // EditView has an 'output area' which is used to clip the paint area we provide below.
+ // So they need to be in the same coordinates/units. This is tied to the mapmode of the gridwin
+ // attached to the EditView, so we have to change its mapmode too (temporarily). We save the
+ // original mapmode and 'output area' and roll them back when we finish painting to rDevice.
+ const tools::Rectangle aOrigOutputArea(pEditView->GetOutputArea()); // Not in pixels.
+ const MapMode aOrigMapMode = GetMapMode();
+ SetMapMode(rDevice.GetMapMode());
+ pEditView->SetOutputArea(rDevice.PixelToLogic(aEditRect));
+ pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice);
+
+ // Now we need to get relative cursor position within the editview.
+ // This is for sending the absolute twips position of the cursor to the specific views with
+ // the same given zoom level.
+ tools::Rectangle aCursorRect = pEditView->GetEditCursor();
+ Point aCursPos = OutputDevice::LogicToLogic(aCursorRect.TopLeft(), MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip));
+
+ // Rollback the mapmode and 'output area'.
+ SetMapMode(aOrigMapMode);
+ pEditView->SetOutputArea(aOrigOutputArea);
+
+ const MapMode& rDevMM = rDevice.GetMapMode();
+ MapMode aMM(MapUnit::MapTwip);
+ aMM.SetScaleX(rDevMM.GetScaleX());
+ aMM.SetScaleY(rDevMM.GetScaleY());
+
+ aBGAbs.AdjustLeft(1);
+ aBGAbs.AdjustTop(1);
+ aCursorRect = OutputDevice::PixelToLogic(aBGAbs, aMM);
+ aCursorRect.setWidth(0);
+ aCursorRect.Move(aCursPos.getX(), 0);
+ // Sends view cursor position to views of all matching zooms if needed (avoids duplicates).
+ InvalidateLOKViewCursor(aCursorRect, aMM.GetScaleX(), aMM.GetScaleY());
+ }
+ else
+ {
+ tools::Rectangle aEditRect(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
+ pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice);
+ }
+
rDevice.SetMapMode(MapMode(MapUnit::MapPixel));
// restore the cursor it was originally visible
diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index cef40898bce6..f4462eb7262c 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -1460,6 +1460,7 @@ void ScViewData::SetEditEngine( ScSplitPos eWhich,
if (comphelper::LibreOfficeKit::isActive())
{
+ pEditView[eWhich]->SetBroadcastLOKViewCursor(false);
pEditView[eWhich]->RegisterViewShell(pViewShell);
}
}