summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2016-07-27 17:07:47 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2016-07-27 16:27:16 +0000
commit5f65ca15a2297f298536d07cfa8564a1f7c67abb (patch)
treedf14d2a9b4a6f69774cc25a704094f6c5422d71e
parenta02f7aa735c52f5d20df0e2a94cc06879cb3dfac (diff)
svx lok: fix handling of text edit drawing when view/page changes
This is a follow-up to commit 9d91d371e92548c7f75a7d0155eecaf3769fdee6 (svx lok: draw text edits in all views, 2016-07-26). Two corner-cases are now handled: 1) When the SfxViewShell is created after begin text edit and 2) When the other draw view is already created, but at the time begin text edit happens, the other draw view shows a different page. And the opposite of these: switching away from a page were we observe a text edit done in an other view or destroying a view that observes a text edit. When the complete view goes away, then SdrObjEditView::HideSdrPage() is not called, so also try to destroy the outliner view of the text edit from SdrObjEditView::DeleteWindowFromPaintView(). The GetSfxViewShell() call in SdrObjEditView::ShowSdrPage() is important, because we let the other draw view create the outliner view, but the outliner view should invoke our view shell, not the view shell of the other draw view. Also improve the SdTiledRenderingTest::testCursorViews() testcase, so that it asserts it managed to begin text edit and use a test document that still has a single slide and shape, but the shape is not auto-sized; otherwise invalidations happen even if outliner views are not created in all draw views, so the test would pass even without the fixes. Change-Id: I2c3bb27826c6887115366db818599fc8adabc5a5 Reviewed-on: https://gerrit.libreoffice.org/27583 Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk> Tested-by: Jenkins <ci@libreoffice.org>
-rw-r--r--include/svx/svdedxv.hxx4
-rw-r--r--sd/qa/unit/tiledrendering/data/title-shape.odpbin0 -> 11406 bytes
-rw-r--r--sd/qa/unit/tiledrendering/tiledrendering.cxx36
-rw-r--r--svx/source/svdraw/svdedxv.cxx76
4 files changed, 107 insertions, 9 deletions
diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx
index 70ffe3b9be0d..452708645c3d 100644
--- a/include/svx/svdedxv.hxx
+++ b/include/svx/svdedxv.hxx
@@ -110,7 +110,7 @@ protected:
// Create a new OutlinerView at the heap and initialize all required parameters.
// pTextEditObj, pTextEditPV and pTextEditOutliner have to be initialized
- OutlinerView* ImpMakeOutlinerView(vcl::Window* pWin, bool bNoPaint, OutlinerView* pGivenView) const;
+ OutlinerView* ImpMakeOutlinerView(vcl::Window* pWin, bool bNoPaint, OutlinerView* pGivenView, SfxViewShell* pViewShell = 0) const;
void ImpPaintOutlinerView(OutlinerView& rOutlView, const Rectangle& rRect, OutputDevice& rTargetDevice) const;
void ImpInvalidateOutlinerView(OutlinerView& rOutlView) const;
@@ -156,6 +156,8 @@ public:
virtual void BckAction() override;
virtual void TakeActionRect(Rectangle& rRect) const override;
+ SdrPageView* ShowSdrPage(SdrPage* pPage) override;
+ void HideSdrPage() override;
/// Get access to the view shell owning this draw view, if any.
virtual SfxViewShell* GetSfxViewShell() const;
diff --git a/sd/qa/unit/tiledrendering/data/title-shape.odp b/sd/qa/unit/tiledrendering/data/title-shape.odp
new file mode 100644
index 000000000000..15d39d68e1ef
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/title-shape.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 3822664c40e9..603efff3f0bd 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -828,13 +828,15 @@ public:
int m_nPart;
bool m_bCursorVisibleChanged;
bool m_bViewLock;
+ bool m_bTilesInvalidated;
ViewCallback()
: m_bGraphicSelectionInvalidated(false),
m_bGraphicViewSelectionInvalidated(false),
m_nPart(0),
m_bCursorVisibleChanged(false),
- m_bViewLock(false)
+ m_bViewLock(false),
+ m_bTilesInvalidated(false)
{
}
@@ -847,6 +849,11 @@ public:
{
switch (nType)
{
+ case LOK_CALLBACK_INVALIDATE_TILES:
+ {
+ m_bTilesInvalidated = true;
+ }
+ break;
case LOK_CALLBACK_GRAPHIC_SELECTION:
{
m_bGraphicSelectionInvalidated = true;
@@ -955,17 +962,20 @@ void SdTiledRenderingTest::testCursorViews()
comphelper::LibreOfficeKit::setActive();
// Create the first view.
- SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
ViewCallback aView1;
+ int nView1 = SfxLokHelper::getView();
SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1);
// Begin text edit on the only object on the slide.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
- SdPage* pActualPage = pViewShell->GetActualPage();
- SdrObject* pObject = pActualPage->GetObj(0);
SdrView* pView = pViewShell->GetView();
- pView->MarkObj(pObject, pView->GetSdrPageView());
- pView->SdrBeginTextEdit(pObject);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pView->IsTextEdit());
// Make sure that cursor state is not changed just because we create a second view.
aView1.m_bCursorVisibleChanged = false;
@@ -974,6 +984,20 @@ void SdTiledRenderingTest::testCursorViews()
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT(!aView1.m_bCursorVisibleChanged);
+ // Make sure that typing in the first view causes an invalidation in the
+ // second view as well, even if the second view was created after begin
+ // text edit in the first view.
+ ViewCallback aView2;
+ SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2);
+ SfxLokHelper::setView(nView1);
+ aView2.m_bTilesInvalidated = false;
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+ Scheduler::ProcessEventsToIdle();
+ // This failed: the second view was not invalidated when pressing a key in
+ // the first view.
+ CPPUNIT_ASSERT(aView2.m_bTilesInvalidated);
+
mxComponent->dispose();
mxComponent.clear();
comphelper::LibreOfficeKit::setActive(false);
diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx
index cd6e083eac5f..e68006e40ce4 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -133,6 +133,76 @@ void SdrObjEditView::BrkAction()
SdrGlueEditView::BrkAction();
}
+SdrPageView* SdrObjEditView::ShowSdrPage(SdrPage* pPage)
+{
+ SdrPageView* pPageView = SdrGlueEditView::ShowSdrPage(pPage);
+
+ if (comphelper::LibreOfficeKit::isActive() && pPageView)
+ {
+ // Check if other views have an active text edit on the same page as
+ // this one.
+ SdrViewIter aIter(pPageView->GetPage());
+ for (SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView())
+ {
+ if (pView == this || !pView->IsTextEdit())
+ continue;
+
+ OutputDevice* pOutDev = GetFirstOutputDevice();
+ if (!pOutDev || pOutDev->GetOutDevType() != OUTDEV_WINDOW)
+ continue;
+
+ // Found one, so create an outliner view, to get invalidations when
+ // the text edit changes.
+ bool bEmpty = pView->GetTextEditObject()->GetOutlinerParaObject() == nullptr;
+ // Call GetSfxViewShell() to make sure ImpMakeOutlinerView()
+ // registers the view shell of this draw view, and not the view
+ // shell of pView.
+ OutlinerView* pOutlinerView = pView->ImpMakeOutlinerView(static_cast<vcl::Window*>(pOutDev), !bEmpty, nullptr, GetSfxViewShell());
+ pView->GetTextEditOutliner()->InsertView(pOutlinerView);
+ }
+ }
+
+ return pPageView;
+}
+
+/// Removes outliner views registered in other draw views that use pOutputDevice.
+void lcl_RemoveTextEditOutlinerViews(SdrObjEditView* pThis, SdrPageView* pPageView, OutputDevice* pOutputDevice)
+{
+ if (!comphelper::LibreOfficeKit::isActive())
+ return;
+
+ if (!pPageView)
+ return;
+
+ if (!pOutputDevice || pOutputDevice->GetOutDevType() != OUTDEV_WINDOW)
+ return;
+
+ SdrViewIter aIter(pPageView->GetPage());
+ for (SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView())
+ {
+ if (pView == pThis || !pView->IsTextEdit())
+ continue;
+
+ SdrOutliner* pOutliner = pView->GetTextEditOutliner();
+ for (size_t nView = 0; nView < pOutliner->GetViewCount(); ++nView)
+ {
+ OutlinerView* pOutlinerView = pOutliner->GetView(nView);
+ if (pOutlinerView->GetWindow() != pOutputDevice)
+ continue;
+
+ pOutliner->RemoveView(pOutlinerView);
+ delete pOutlinerView;
+ }
+ }
+}
+
+void SdrObjEditView::HideSdrPage()
+{
+ lcl_RemoveTextEditOutlinerViews(this, GetSdrPageView(), GetFirstOutputDevice());
+
+ SdrGlueEditView::HideSdrPage();
+}
+
void SdrObjEditView::TakeActionRect(Rectangle& rRect) const
{
if (IsMacroObj()) {
@@ -442,7 +512,7 @@ void SdrObjEditView::ImpInvalidateOutlinerView(OutlinerView& rOutlView) const
}
}
-OutlinerView* SdrObjEditView::ImpMakeOutlinerView(vcl::Window* pWin, bool /*bNoPaint*/, OutlinerView* pGivenView) const
+OutlinerView* SdrObjEditView::ImpMakeOutlinerView(vcl::Window* pWin, bool /*bNoPaint*/, OutlinerView* pGivenView, SfxViewShell* pViewShell) const
{
// background
Color aBackground(GetTextEditBackgroundColor(*this));
@@ -471,7 +541,7 @@ OutlinerView* SdrObjEditView::ImpMakeOutlinerView(vcl::Window* pWin, bool /*bNoP
// SfxViewShell::Current() may still point to the old one. So if possible,
// depend on the application owning this draw view to provide the view
// shell.
- SfxViewShell* pSfxViewShell = GetSfxViewShell();
+ SfxViewShell* pSfxViewShell = pViewShell ? pViewShell : GetSfxViewShell();
pOutlView->registerLibreOfficeKitViewCallback(pSfxViewShell ? pSfxViewShell : SfxViewShell::Current());
if (pText!=nullptr)
@@ -1853,6 +1923,8 @@ void SdrObjEditView::DeleteWindowFromPaintView(OutputDevice* pOldWin)
}
}
}
+
+ lcl_RemoveTextEditOutlinerViews(this, GetSdrPageView(), pOldWin);
}
bool SdrObjEditView::IsTextEditInSelectionMode() const