1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <boost/property_tree/json_parser.hpp>
13 #include <com/sun/star/frame/DispatchResultState.hpp>
14 #include <swmodeltestbase.hxx>
15 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
16 #include <comphelper/dispatchcommand.hxx>
17 #include <comphelper/propertysequence.hxx>
18 #include <comphelper/string.hxx>
19 #include <comphelper/lok.hxx>
20 #include <svx/svdpage.hxx>
21 #include <svx/svdview.hxx>
22 #include <vcl/svapp.hxx>
23 #include <editeng/editview.hxx>
24 #include <editeng/outliner.hxx>
25 #include <svl/srchitem.hxx>
26 #include <drawdoc.hxx>
30 #include <UndoManager.hxx>
32 #include <sfx2/viewsh.hxx>
33 #include <sfx2/bindings.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <sfx2/viewfrm.hxx>
36 #include <sfx2/lokhelper.hxx>
37 #include <redline.hxx>
38 #include <IDocumentRedlineAccess.hxx>
39 #include <vcl/scheduler.hxx>
41 static char const DATA_DIRECTORY
[] = "/sw/qa/extras/tiledrendering/data/";
43 static std::ostream
& operator<<(std::ostream
& os
, ViewShellId id
)
49 /// Testsuite for the SwXTextDocument methods implementing the vcl::ITiledRenderable interface.
50 class SwTiledRenderingTest
: public SwModelTestBase
53 SwTiledRenderingTest();
54 void testRegisterCallback();
55 void testPostKeyEvent();
56 void testPostMouseEvent();
57 void testSetTextSelection();
58 void testGetTextSelection();
59 void testSetGraphicSelection();
60 void testResetSelection();
62 void testSearchViewArea();
63 void testSearchTextFrame();
64 void testSearchTextFrameWrapAround();
65 void testDocumentSizeChanged();
67 void testSearchAllNotifications();
68 void testPageDownInvalidation();
70 void testViewCursors();
71 void testShapeViewCursors();
72 void testMissingInvalidation();
73 void testViewCursorVisibility();
74 void testViewCursorCleanup();
76 void testTextEditViewInvalidations();
77 void testUndoInvalidations();
78 void testUndoLimiting();
79 void testUndoShapeLimiting();
80 void testUndoDispatch();
81 void testUndoRepairDispatch();
82 void testShapeTextUndoShells();
83 void testShapeTextUndoGroupShells();
84 void testTrackChanges();
85 void testTrackChangesCallback();
86 void testRedlineUpdateCallback();
87 void testSetViewGraphicSelection();
88 void testCreateViewGraphicSelection();
89 void testCreateViewTextSelection();
90 void testRedlineColors();
91 void testCommentEndTextEdit();
92 void testCursorPosition();
93 void testPaintCallbacks();
94 void testUndoRepairResult();
95 void testRedoRepairResult();
96 void testDisableUndoRepair();
97 void testAllTrackedChanges();
98 void testDocumentRepair();
100 CPPUNIT_TEST_SUITE(SwTiledRenderingTest
);
101 CPPUNIT_TEST(testRegisterCallback
);
102 CPPUNIT_TEST(testPostKeyEvent
);
103 CPPUNIT_TEST(testPostMouseEvent
);
104 CPPUNIT_TEST(testSetTextSelection
);
105 CPPUNIT_TEST(testGetTextSelection
);
106 CPPUNIT_TEST(testSetGraphicSelection
);
107 CPPUNIT_TEST(testResetSelection
);
108 CPPUNIT_TEST(testSearch
);
109 CPPUNIT_TEST(testSearchViewArea
);
110 CPPUNIT_TEST(testSearchTextFrame
);
111 CPPUNIT_TEST(testSearchTextFrameWrapAround
);
112 CPPUNIT_TEST(testDocumentSizeChanged
);
113 CPPUNIT_TEST(testSearchAll
);
114 CPPUNIT_TEST(testSearchAllNotifications
);
115 CPPUNIT_TEST(testPageDownInvalidation
);
116 CPPUNIT_TEST(testPartHash
);
117 CPPUNIT_TEST(testViewCursors
);
118 CPPUNIT_TEST(testShapeViewCursors
);
119 CPPUNIT_TEST(testMissingInvalidation
);
120 CPPUNIT_TEST(testViewCursorVisibility
);
121 CPPUNIT_TEST(testViewCursorCleanup
);
122 CPPUNIT_TEST(testViewLock
);
123 CPPUNIT_TEST(testTextEditViewInvalidations
);
124 CPPUNIT_TEST(testUndoInvalidations
);
125 CPPUNIT_TEST(testUndoLimiting
);
126 CPPUNIT_TEST(testUndoShapeLimiting
);
127 CPPUNIT_TEST(testUndoDispatch
);
128 CPPUNIT_TEST(testUndoRepairDispatch
);
129 CPPUNIT_TEST(testShapeTextUndoShells
);
130 CPPUNIT_TEST(testShapeTextUndoGroupShells
);
131 CPPUNIT_TEST(testTrackChanges
);
132 CPPUNIT_TEST(testTrackChangesCallback
);
133 CPPUNIT_TEST(testRedlineUpdateCallback
);
134 CPPUNIT_TEST(testSetViewGraphicSelection
);
135 CPPUNIT_TEST(testCreateViewGraphicSelection
);
136 CPPUNIT_TEST(testCreateViewTextSelection
);
137 CPPUNIT_TEST(testRedlineColors
);
138 CPPUNIT_TEST(testCommentEndTextEdit
);
139 CPPUNIT_TEST(testCursorPosition
);
140 CPPUNIT_TEST(testPaintCallbacks
);
141 CPPUNIT_TEST(testUndoRepairResult
);
142 CPPUNIT_TEST(testRedoRepairResult
);
143 CPPUNIT_TEST(testDisableUndoRepair
);
144 CPPUNIT_TEST(testAllTrackedChanges
);
145 CPPUNIT_TEST(testDocumentRepair
);
147 CPPUNIT_TEST_SUITE_END();
150 SwXTextDocument
* createDoc(const char* pName
= nullptr);
151 static void callback(int nType
, const char* pPayload
, void* pData
);
152 void callbackImpl(int nType
, const char* pPayload
);
153 tools::Rectangle m_aInvalidation
;
154 Size m_aDocumentSize
;
155 OString m_aTextSelection
;
157 std::vector
<OString
> m_aSearchResultSelection
;
158 std::vector
<int> m_aSearchResultPart
;
159 int m_nSelectionBeforeSearchResult
;
160 int m_nSelectionAfterSearchResult
;
161 int m_nInvalidations
;
162 int m_nRedlineTableSizeChanged
;
163 int m_nRedlineTableEntryModified
;
164 int m_nTrackedChangeIndex
;
167 SwTiledRenderingTest::SwTiledRenderingTest()
169 m_nSelectionBeforeSearchResult(0),
170 m_nSelectionAfterSearchResult(0),
172 m_nRedlineTableSizeChanged(0),
173 m_nRedlineTableEntryModified(0),
174 m_nTrackedChangeIndex(-1)
178 SwXTextDocument
* SwTiledRenderingTest::createDoc(const char* pName
)
181 loadURL("private:factory/swriter", nullptr);
183 load(DATA_DIRECTORY
, pName
);
185 SwXTextDocument
* pTextDocument
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
186 CPPUNIT_ASSERT(pTextDocument
);
187 pTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
188 return pTextDocument
;
191 void SwTiledRenderingTest::callback(int nType
, const char* pPayload
, void* pData
)
193 static_cast<SwTiledRenderingTest
*>(pData
)->callbackImpl(nType
, pPayload
);
196 void SwTiledRenderingTest::callbackImpl(int nType
, const char* pPayload
)
198 OString
aPayload(pPayload
);
201 case LOK_CALLBACK_INVALIDATE_TILES
:
203 if (m_aInvalidation
.IsEmpty())
205 uno::Sequence
<OUString
> aSeq
= comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload
));
206 if (OString("EMPTY") == pPayload
)
208 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(4), aSeq
.getLength());
209 m_aInvalidation
.setX(aSeq
[0].toInt32());
210 m_aInvalidation
.setY(aSeq
[1].toInt32());
211 m_aInvalidation
.setWidth(aSeq
[2].toInt32());
212 m_aInvalidation
.setHeight(aSeq
[3].toInt32());
217 case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED
:
219 uno::Sequence
<OUString
> aSeq
= comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload
));
220 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(2), aSeq
.getLength());
221 m_aDocumentSize
.setWidth(aSeq
[0].toInt32());
222 m_aDocumentSize
.setHeight(aSeq
[1].toInt32());
225 case LOK_CALLBACK_TEXT_SELECTION
:
227 m_aTextSelection
= pPayload
;
228 if (m_aSearchResultSelection
.empty())
229 ++m_nSelectionBeforeSearchResult
;
231 ++m_nSelectionAfterSearchResult
;
234 case LOK_CALLBACK_SEARCH_NOT_FOUND
:
239 case LOK_CALLBACK_SEARCH_RESULT_SELECTION
:
241 m_aSearchResultSelection
.clear();
242 boost::property_tree::ptree aTree
;
243 std::stringstream
aStream(pPayload
);
244 boost::property_tree::read_json(aStream
, aTree
);
245 for (boost::property_tree::ptree::value_type
& rValue
: aTree
.get_child("searchResultSelection"))
247 m_aSearchResultSelection
.emplace_back(rValue
.second
.get
<std::string
>("rectangles").c_str());
248 m_aSearchResultPart
.push_back(std::atoi(rValue
.second
.get
<std::string
>("part").c_str()));
252 case LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED
:
254 ++m_nRedlineTableSizeChanged
;
257 case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED
:
259 ++m_nRedlineTableEntryModified
;
262 case LOK_CALLBACK_STATE_CHANGED
:
264 OString
aTrackedChangeIndexPrefix(".uno:TrackedChangeIndex=");
265 if (aPayload
.startsWith(aTrackedChangeIndexPrefix
))
267 OString sIndex
= aPayload
.copy(aTrackedChangeIndexPrefix
.getLength());
268 if (sIndex
.isEmpty())
269 m_nTrackedChangeIndex
= -1;
271 m_nTrackedChangeIndex
= sIndex
.toInt32();
278 void SwTiledRenderingTest::testRegisterCallback()
280 comphelper::LibreOfficeKit::setActive();
281 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
282 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
283 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
284 // Insert a character at the beginning of the document.
285 pWrtShell
->Insert("x");
287 // Check that the top left 256x256px tile would be invalidated.
288 CPPUNIT_ASSERT(!m_aInvalidation
.IsEmpty());
289 tools::Rectangle
aTopLeft(0, 0, 256*15, 256*15); // 1 px = 15 twips, assuming 96 DPI.
290 CPPUNIT_ASSERT(m_aInvalidation
.IsOver(aTopLeft
));
291 comphelper::LibreOfficeKit::setActive(false);
294 void SwTiledRenderingTest::testPostKeyEvent()
296 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
297 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
298 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
299 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
300 // Did we manage to go after the first character?
301 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), pShellCursor
->GetPoint()->nContent
.GetIndex());
303 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
304 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
305 // Did we manage to insert the character after the first one?
306 CPPUNIT_ASSERT_EQUAL(OUString("Axaa bbb."), pShellCursor
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText());
309 void SwTiledRenderingTest::testPostMouseEvent()
311 comphelper::LibreOfficeKit::setActive();
312 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
313 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
314 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
315 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
316 // Did we manage to go after the first character?
317 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), pShellCursor
->GetPoint()->nContent
.GetIndex());
319 Point aStart
= pShellCursor
->GetSttPos();
320 aStart
.setX(aStart
.getX() - 1000);
321 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN
, aStart
.getX(), aStart
.getY(), 1, MOUSE_LEFT
, 0);
322 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP
, aStart
.getX(), aStart
.getY(), 1, MOUSE_LEFT
, 0);
323 // The new cursor position must be before the first word.
324 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0), pShellCursor
->GetPoint()->nContent
.GetIndex());
325 comphelper::LibreOfficeKit::setActive(false);
328 void SwTiledRenderingTest::testSetTextSelection()
330 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
331 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
332 // Move the cursor into the second word.
333 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 5, /*bBasicCall=*/false);
334 // Create a selection on the word.
336 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
337 // Did we indeed manage to select the second word?
338 CPPUNIT_ASSERT_EQUAL(OUString("bbb"), pShellCursor
->GetText());
340 // Now use setTextSelection() to move the start of the selection 1000 twips left.
341 Point aStart
= pShellCursor
->GetSttPos();
342 aStart
.setX(aStart
.getX() - 1000);
343 pXTextDocument
->setTextSelection(LOK_SETTEXTSELECTION_START
, aStart
.getX(), aStart
.getY());
344 // The new selection must include the first word, too -- but not the ending dot.
345 CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb"), pShellCursor
->GetText());
347 // Next: test that LOK_SETTEXTSELECTION_RESET + LOK_SETTEXTSELECTION_END can be used to create a selection.
348 pXTextDocument
->setTextSelection(LOK_SETTEXTSELECTION_RESET
, aStart
.getX(), aStart
.getY());
349 pXTextDocument
->setTextSelection(LOK_SETTEXTSELECTION_END
, aStart
.getX() + 1000, aStart
.getY());
350 CPPUNIT_ASSERT_EQUAL(OUString("Aaa b"), pShellCursor
->GetText());
353 void SwTiledRenderingTest::testGetTextSelection()
355 comphelper::LibreOfficeKit::setActive();
357 SwXTextDocument
* pXTextDocument
= createDoc("shape-with-text.fodt");
358 // No crash, just empty output for unexpected mime type.
360 CPPUNIT_ASSERT_EQUAL(OString(), pXTextDocument
->getTextSelection("foo/bar", aUsedFormat
));
362 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
363 // Move the cursor into the first word.
364 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 2, /*bBasicCall=*/false);
365 // Create a selection by on the word.
368 // Make sure that we selected text from the body text.
369 CPPUNIT_ASSERT_EQUAL(OString("Hello"), pXTextDocument
->getTextSelection("text/plain;charset=utf-8", aUsedFormat
));
371 // Make sure we produce something for HTML.
372 CPPUNIT_ASSERT(!pXTextDocument
->getTextSelection("text/html", aUsedFormat
).isEmpty());
374 // Now select some shape text and check again.
375 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
376 SdrObject
* pObject
= pPage
->GetObj(0);
377 SdrView
* pView
= pWrtShell
->GetDrawView();
378 pView
->SdrBeginTextEdit(pObject
);
379 CPPUNIT_ASSERT(pView
->GetTextEditObject());
380 EditView
& rEditView
= pView
->GetTextEditOutlinerView()->GetEditView();
381 ESelection
aWordSelection(0, 0, 0, 5);
382 rEditView
.SetSelection(aWordSelection
);
383 CPPUNIT_ASSERT_EQUAL(OString("Shape"), pXTextDocument
->getTextSelection("text/plain;charset=utf-8", aUsedFormat
));
385 comphelper::LibreOfficeKit::setActive(false);
388 void SwTiledRenderingTest::testSetGraphicSelection()
390 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
391 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
392 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
393 SdrObject
* pObject
= pPage
->GetObj(0);
394 pWrtShell
->SelectObj(Point(), 0, pObject
);
395 // Make sure the rectangle has 8 handles: at each corner and at the center of each edge.
396 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(8), pObject
->GetHdlCount());
397 // Take the bottom center one.
398 SdrHdl
* pHdl
= pObject
->GetHdl(6);
399 CPPUNIT_ASSERT_EQUAL((int)SdrHdlKind::Lower
, (int)pHdl
->GetKind());
400 tools::Rectangle aShapeBefore
= pObject
->GetSnapRect();
402 pXTextDocument
->setGraphicSelection(LOK_SETGRAPHICSELECTION_START
, pHdl
->GetPos().getX(), pHdl
->GetPos().getY());
403 pXTextDocument
->setGraphicSelection(LOK_SETGRAPHICSELECTION_END
, pHdl
->GetPos().getX(), pHdl
->GetPos().getY() + 1000);
404 tools::Rectangle aShapeAfter
= pObject
->GetSnapRect();
405 // Check that a resize happened, but aspect ratio is not kept.
406 CPPUNIT_ASSERT_EQUAL(aShapeBefore
.getWidth(), aShapeAfter
.getWidth());
407 CPPUNIT_ASSERT_EQUAL(aShapeBefore
.getHeight() + 1000, aShapeAfter
.getHeight());
410 void SwTiledRenderingTest::testResetSelection()
412 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
413 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
414 // Select one character.
415 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/true, 1, /*bBasicCall=*/false);
416 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
417 // We have a text selection.
418 CPPUNIT_ASSERT(pShellCursor
->HasMark());
420 pXTextDocument
->resetSelection();
421 // We no longer have a text selection.
422 CPPUNIT_ASSERT(!pShellCursor
->HasMark());
424 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
425 SdrObject
* pObject
= pPage
->GetObj(0);
426 Point aPoint
= pObject
->GetSnapRect().Center();
428 pWrtShell
->EnterSelFrameMode(&aPoint
);
429 // We have a graphic selection.
430 CPPUNIT_ASSERT(pWrtShell
->IsSelFrameMode());
432 pXTextDocument
->resetSelection();
433 // We no longer have a graphic selection.
434 CPPUNIT_ASSERT(!pWrtShell
->IsSelFrameMode());
437 void lcl_search(bool bBackward
)
439 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
441 {"SearchItem.SearchString", uno::makeAny(OUString("shape"))},
442 {"SearchItem.Backward", uno::makeAny(bBackward
)}
444 comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues
);
447 void SwTiledRenderingTest::testSearch()
449 comphelper::LibreOfficeKit::setActive();
451 SwXTextDocument
* pXTextDocument
= createDoc("search.odt");
452 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
453 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
454 std::size_t nNode
= pWrtShell
->getShellCursor(false)->Start()->nNode
.GetNode().GetIndex();
456 // First hit, in the second paragraph, before the shape.
458 CPPUNIT_ASSERT(!pWrtShell
->GetDrawView()->GetTextEditObject());
459 std::size_t nActual
= pWrtShell
->getShellCursor(false)->Start()->nNode
.GetNode().GetIndex();
460 CPPUNIT_ASSERT_EQUAL(nNode
+ 1, nActual
);
461 /// Make sure we get search result selection for normal find as well, not only find all.
462 CPPUNIT_ASSERT(!m_aSearchResultSelection
.empty());
464 // Next hit, in the shape.
466 CPPUNIT_ASSERT(pWrtShell
->GetDrawView()->GetTextEditObject());
468 // Next hit, in the shape, still.
470 CPPUNIT_ASSERT(pWrtShell
->GetDrawView()->GetTextEditObject());
472 // Last hit, in the last paragraph, after the shape.
474 CPPUNIT_ASSERT(!pWrtShell
->GetDrawView()->GetTextEditObject());
475 nActual
= pWrtShell
->getShellCursor(false)->Start()->nNode
.GetNode().GetIndex();
476 CPPUNIT_ASSERT_EQUAL(nNode
+ 7, nActual
);
478 // Now change direction and make sure that the first 2 hits are in the shape, but not the 3rd one.
480 CPPUNIT_ASSERT(pWrtShell
->GetDrawView()->GetTextEditObject());
482 CPPUNIT_ASSERT(pWrtShell
->GetDrawView()->GetTextEditObject());
484 CPPUNIT_ASSERT(!pWrtShell
->GetDrawView()->GetTextEditObject());
485 nActual
= pWrtShell
->getShellCursor(false)->Start()->nNode
.GetNode().GetIndex();
486 CPPUNIT_ASSERT_EQUAL(nNode
+ 1, nActual
);
488 comphelper::LibreOfficeKit::setActive(false);
491 void SwTiledRenderingTest::testSearchViewArea()
493 SwXTextDocument
* pXTextDocument
= createDoc("search.odt");
494 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
495 // Go to the second page, 1-based.
496 pWrtShell
->GotoPage(2, false);
497 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
498 // Get the ~top left corner of the second page.
499 Point aPoint
= pShellCursor
->GetSttPos();
501 // Go back to the first page, search while the cursor is there, but the
502 // visible area is the second page.
503 pWrtShell
->GotoPage(1, false);
504 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
506 {"SearchItem.SearchString", uno::makeAny(OUString("Heading"))},
507 {"SearchItem.Backward", uno::makeAny(false)},
508 {"SearchItem.SearchStartPointX", uno::makeAny(static_cast<sal_Int32
>(aPoint
.getX()))},
509 {"SearchItem.SearchStartPointY", uno::makeAny(static_cast<sal_Int32
>(aPoint
.getY()))}
511 comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues
);
512 // This was just "Heading", i.e. SwView::SearchAndWrap() did not search from only the top of the second page.
513 CPPUNIT_ASSERT_EQUAL(OUString("Heading on second page"), pShellCursor
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText());
516 void SwTiledRenderingTest::testSearchTextFrame()
518 comphelper::LibreOfficeKit::setActive();
520 SwXTextDocument
* pXTextDocument
= createDoc("search.odt");
521 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
522 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
523 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
525 {"SearchItem.SearchString", uno::makeAny(OUString("TextFrame"))},
526 {"SearchItem.Backward", uno::makeAny(false)},
528 comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues
);
529 // This was empty: nothing was highlighted after searching for 'TextFrame'.
530 CPPUNIT_ASSERT(!m_aTextSelection
.isEmpty());
532 comphelper::LibreOfficeKit::setActive(false);
535 void SwTiledRenderingTest::testSearchTextFrameWrapAround()
537 SwXTextDocument
* pXTextDocument
= createDoc("search.odt");
538 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
539 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
540 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
542 {"SearchItem.SearchString", uno::makeAny(OUString("TextFrame"))},
543 {"SearchItem.Backward", uno::makeAny(false)},
545 comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues
);
546 CPPUNIT_ASSERT(m_bFound
);
547 comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues
);
548 // This failed, i.e. the second time 'not found' was reported, instead of wrapping around.
549 CPPUNIT_ASSERT(m_bFound
);
552 void SwTiledRenderingTest::testDocumentSizeChanged()
554 comphelper::LibreOfficeKit::setActive();
555 // Get the current document size.
556 SwXTextDocument
* pXTextDocument
= createDoc("2-pages.odt");
557 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
558 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
559 Size aSize
= pXTextDocument
->getDocumentSize();
561 // Delete the second page and see how the size changes.
562 pWrtShell
->Down(false);
563 pWrtShell
->DelLeft();
564 // Document width should not change, this was 0.
565 CPPUNIT_ASSERT_EQUAL(aSize
.getWidth(), m_aDocumentSize
.getWidth());
566 // Document height should be smaller now.
567 CPPUNIT_ASSERT(aSize
.getHeight() > m_aDocumentSize
.getHeight());
568 comphelper::LibreOfficeKit::setActive(false);
571 void SwTiledRenderingTest::testSearchAll()
573 comphelper::LibreOfficeKit::setActive();
575 SwXTextDocument
* pXTextDocument
= createDoc("search.odt");
576 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
577 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
578 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
580 {"SearchItem.SearchString", uno::makeAny(OUString("shape"))},
581 {"SearchItem.Backward", uno::makeAny(false)},
582 {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16
>(SvxSearchCmd::FIND_ALL
))},
584 comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues
);
585 // This was 0; should be 2 results in the body text.
586 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), m_aSearchResultSelection
.size());
587 // Writer documents are always a single part.
588 CPPUNIT_ASSERT_EQUAL(0, m_aSearchResultPart
[0]);
590 comphelper::LibreOfficeKit::setActive(false);
593 void SwTiledRenderingTest::testSearchAllNotifications()
595 comphelper::LibreOfficeKit::setActive();
596 SwXTextDocument
* pXTextDocument
= createDoc("search.odt");
597 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
598 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
599 // Reset notification counter before search.
600 m_nSelectionBeforeSearchResult
= 0;
601 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
603 {"SearchItem.SearchString", uno::makeAny(OUString("shape"))},
604 {"SearchItem.Backward", uno::makeAny(false)},
605 {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16
>(SvxSearchCmd::FIND_ALL
))},
607 comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues
);
608 Scheduler::ProcessEventsToIdle();
610 // This was 5, make sure that we get no notifications about selection changes during search.
611 CPPUNIT_ASSERT_EQUAL(0, m_nSelectionBeforeSearchResult
);
612 // But we do get the selection afterwards.
613 CPPUNIT_ASSERT(m_nSelectionAfterSearchResult
> 0);
615 comphelper::LibreOfficeKit::setActive(false);
618 void SwTiledRenderingTest::testPageDownInvalidation()
620 comphelper::LibreOfficeKit::setActive();
622 SwXTextDocument
* pXTextDocument
= createDoc("pagedown-invalidation.odt");
623 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
625 {".uno:HideWhitespace", uno::makeAny(true)},
627 pXTextDocument
->initializeForTiledRendering(aPropertyValues
);
628 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
629 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
630 comphelper::dispatchCommand(".uno:PageDown", uno::Sequence
<beans::PropertyValue
>());
633 CPPUNIT_ASSERT_EQUAL(0, m_nInvalidations
);
635 comphelper::LibreOfficeKit::setActive(false);
638 void SwTiledRenderingTest::testPartHash()
640 comphelper::LibreOfficeKit::setActive();
642 SwXTextDocument
* pXTextDocument
= createDoc("pagedown-invalidation.odt");
643 int nParts
= pXTextDocument
->getParts();
644 for (int it
= 0; it
< nParts
; it
++)
646 CPPUNIT_ASSERT(!pXTextDocument
->getPartHash(it
).isEmpty());
649 comphelper::LibreOfficeKit::setActive(false);
652 /// A view callback tracks callbacks invoked on one specific view.
656 bool m_bOwnCursorInvalidated
;
657 bool m_bOwnCursorAtOrigin
;
658 tools::Rectangle m_aOwnCursor
;
659 bool m_bViewCursorInvalidated
;
660 tools::Rectangle m_aViewCursor
;
661 bool m_bOwnSelectionSet
;
662 bool m_bViewSelectionSet
;
663 OString m_aViewSelection
;
664 bool m_bTilesInvalidated
;
665 bool m_bViewCursorVisible
;
666 bool m_bGraphicViewSelection
;
667 bool m_bGraphicSelection
;
669 /// Set if any callback was invoked.
671 /// Redline table size changed payload
672 boost::property_tree::ptree m_aRedlineTableChanged
;
673 /// Redline table modified payload
674 boost::property_tree::ptree m_aRedlineTableModified
;
677 : m_bOwnCursorInvalidated(false),
678 m_bOwnCursorAtOrigin(false),
679 m_bViewCursorInvalidated(false),
680 m_bOwnSelectionSet(false),
681 m_bViewSelectionSet(false),
682 m_bTilesInvalidated(false),
683 m_bViewCursorVisible(false),
684 m_bGraphicViewSelection(false),
685 m_bGraphicSelection(false),
691 static void callback(int nType
, const char* pPayload
, void* pData
)
693 static_cast<ViewCallback
*>(pData
)->callbackImpl(nType
, pPayload
);
696 void callbackImpl(int nType
, const char* pPayload
)
698 OString
aPayload(pPayload
);
702 case LOK_CALLBACK_INVALIDATE_TILES
:
704 m_bTilesInvalidated
= true;
707 case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR
:
709 m_bOwnCursorInvalidated
= true;
711 uno::Sequence
<OUString
> aSeq
= comphelper::string::convertCommaSeparated(OUString::fromUtf8(aPayload
));
712 if (OString("EMPTY") == pPayload
)
714 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(4), aSeq
.getLength());
715 m_aOwnCursor
.setX(aSeq
[0].toInt32());
716 m_aOwnCursor
.setY(aSeq
[1].toInt32());
717 m_aOwnCursor
.setWidth(aSeq
[2].toInt32());
718 m_aOwnCursor
.setHeight(aSeq
[3].toInt32());
719 if (m_aOwnCursor
.getX() == 0 && m_aOwnCursor
.getY() == 0)
720 m_bOwnCursorAtOrigin
= true;
723 case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR
:
725 m_bViewCursorInvalidated
= true;
726 std::stringstream
aStream(pPayload
);
727 boost::property_tree::ptree aTree
;
728 boost::property_tree::read_json(aStream
, aTree
);
729 OString aRect
= aTree
.get_child("rectangle").get_value
<std::string
>().c_str();
731 uno::Sequence
<OUString
> aSeq
= comphelper::string::convertCommaSeparated(OUString::fromUtf8(aRect
));
732 if (OString("EMPTY") == pPayload
)
734 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(4), aSeq
.getLength());
735 m_aViewCursor
.setX(aSeq
[0].toInt32());
736 m_aViewCursor
.setY(aSeq
[1].toInt32());
737 m_aViewCursor
.setWidth(aSeq
[2].toInt32());
738 m_aViewCursor
.setHeight(aSeq
[3].toInt32());
741 case LOK_CALLBACK_TEXT_SELECTION
:
743 m_bOwnSelectionSet
= true;
746 case LOK_CALLBACK_TEXT_VIEW_SELECTION
:
748 m_bViewSelectionSet
= true;
749 m_aViewSelection
= aPayload
;
752 case LOK_CALLBACK_VIEW_CURSOR_VISIBLE
:
754 std::stringstream
aStream(pPayload
);
755 boost::property_tree::ptree aTree
;
756 boost::property_tree::read_json(aStream
, aTree
);
757 m_bViewCursorVisible
= aTree
.get_child("visible").get_value
<std::string
>() == "true";
760 case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION
:
762 std::stringstream
aStream(pPayload
);
763 boost::property_tree::ptree aTree
;
764 boost::property_tree::read_json(aStream
, aTree
);
765 m_bGraphicViewSelection
= aTree
.get_child("selection").get_value
<std::string
>() != "EMPTY";
768 case LOK_CALLBACK_GRAPHIC_SELECTION
:
770 m_bGraphicSelection
= aPayload
!= "EMPTY";
773 case LOK_CALLBACK_VIEW_LOCK
:
775 std::stringstream
aStream(pPayload
);
776 boost::property_tree::ptree aTree
;
777 boost::property_tree::read_json(aStream
, aTree
);
778 m_bViewLock
= aTree
.get_child("rectangle").get_value
<std::string
>() != "EMPTY";
781 case LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED
:
783 m_aRedlineTableChanged
.clear();
784 std::stringstream
aStream(pPayload
);
785 boost::property_tree::read_json(aStream
, m_aRedlineTableChanged
);
786 m_aRedlineTableChanged
= m_aRedlineTableChanged
.get_child("redline");
789 case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED
:
791 m_aRedlineTableModified
.clear();
792 std::stringstream
aStream(pPayload
);
793 boost::property_tree::read_json(aStream
, m_aRedlineTableModified
);
794 m_aRedlineTableModified
= m_aRedlineTableModified
.get_child("redline");
801 class TestResultListener
: public cppu::WeakImplHelper
<css::frame::XDispatchResultListener
>
804 sal_uInt32 m_nDocRepair
;
806 TestResultListener() : m_nDocRepair(0)
810 virtual void SAL_CALL
dispatchFinished(const css::frame::DispatchResultEvent
& rEvent
) override
812 if (rEvent
.State
== frame::DispatchResultState::SUCCESS
)
814 rEvent
.Result
>>= m_nDocRepair
;
818 virtual void SAL_CALL
disposing(const css::lang::EventObject
&) override
823 void SwTiledRenderingTest::testMissingInvalidation()
825 comphelper::LibreOfficeKit::setActive();
828 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
830 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
831 int nView1
= SfxLokHelper::getView();
832 SfxLokHelper::createView();
834 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
835 int nView2
= SfxLokHelper::getView();
837 // First view: put the cursor into the first word.
838 SfxLokHelper::setView(nView1
);
839 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
840 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
842 // Second view: select the first word.
843 SfxLokHelper::setView(nView2
);
844 CPPUNIT_ASSERT(pXTextDocument
->GetDocShell()->GetWrtShell() != pWrtShell
);
845 pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
846 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
849 // Now delete the selected word and make sure both views are invalidated.
850 aView1
.m_bTilesInvalidated
= false;
851 aView2
.m_bTilesInvalidated
= false;
852 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::DELETE
);
853 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::DELETE
);
854 Scheduler::ProcessEventsToIdle();
855 CPPUNIT_ASSERT(aView1
.m_bTilesInvalidated
);
856 CPPUNIT_ASSERT(aView2
.m_bTilesInvalidated
);
857 mxComponent
->dispose();
860 comphelper::LibreOfficeKit::setActive(false);
863 void SwTiledRenderingTest::testViewCursors()
865 comphelper::LibreOfficeKit::setActive();
867 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
869 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
870 SfxLokHelper::createView();
872 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
873 CPPUNIT_ASSERT(aView1
.m_bOwnCursorInvalidated
);
874 CPPUNIT_ASSERT(aView1
.m_bViewCursorInvalidated
);
875 CPPUNIT_ASSERT(aView2
.m_bOwnCursorInvalidated
);
876 // This failed: the cursor position of view1 was only known to view2 once
878 CPPUNIT_ASSERT(aView2
.m_bViewCursorInvalidated
);
880 // Make sure that aView1 gets a view-only selection notification, while
881 // aView2 gets a real selection notification.
882 aView1
.m_bOwnSelectionSet
= false;
883 aView1
.m_bViewSelectionSet
= false;
884 aView2
.m_bOwnSelectionSet
= false;
885 aView2
.m_bViewSelectionSet
= false;
886 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
887 // Move the cursor into the second word.
888 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 5, /*bBasicCall=*/false);
889 // Create a selection on the word.
891 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
892 // Did we indeed manage to select the second word?
893 CPPUNIT_ASSERT_EQUAL(OUString("bbb"), pShellCursor
->GetText());
894 CPPUNIT_ASSERT(!aView1
.m_bOwnSelectionSet
);
895 // This failed, aView1 did not get notification about selection changes in
897 CPPUNIT_ASSERT(aView1
.m_bViewSelectionSet
);
898 CPPUNIT_ASSERT(aView2
.m_bOwnSelectionSet
);
899 CPPUNIT_ASSERT(!aView2
.m_bViewSelectionSet
);
900 mxComponent
->dispose();
903 comphelper::LibreOfficeKit::setActive(false);
906 void SwTiledRenderingTest::testShapeViewCursors()
908 comphelper::LibreOfficeKit::setActive();
910 // Load a document and create a view, so we have 2 ones.
911 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
913 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
914 SfxLokHelper::createView();
916 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
917 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
918 SwWrtShell
* pWrtShell2
= pXTextDocument
->GetDocShell()->GetWrtShell();
920 // Start shape text in the second view.
921 SdrPage
* pPage
= pWrtShell2
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
922 SdrObject
* pObject
= pPage
->GetObj(0);
923 SdrView
* pView
= pWrtShell2
->GetDrawView();
924 pWrtShell2
->GetView().BeginTextEdit(pObject
, pView
->GetSdrPageView(), pWrtShell2
->GetWin());
925 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
926 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
928 // Press a key in the second view, while the first one observes this.
929 aView1
.m_bOwnCursorInvalidated
= false;
930 aView1
.m_bViewCursorInvalidated
= false;
931 aView2
.m_bOwnCursorInvalidated
= false;
932 aView2
.m_bViewCursorInvalidated
= false;
933 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'y', 0);
934 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'y', 0);
935 // Make sure that aView1 gets a view-only cursor notification, while
936 // aView2 gets a real cursor notification.
937 CPPUNIT_ASSERT(!aView1
.m_bOwnCursorInvalidated
);
938 CPPUNIT_ASSERT(aView1
.m_bViewCursorInvalidated
);
939 CPPUNIT_ASSERT(aView2
.m_bOwnCursorInvalidated
);
940 CPPUNIT_ASSERT(!aView2
.m_bViewCursorInvalidated
);
941 mxComponent
->dispose();
944 comphelper::LibreOfficeKit::setActive(false);
947 void SwTiledRenderingTest::testViewCursorVisibility()
949 comphelper::LibreOfficeKit::setActive();
951 // Load a document that has a shape and create two views.
952 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
954 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
955 SfxLokHelper::createView();
956 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
958 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
959 // This failed, initially the view cursor in the second view wasn't visible.
960 CPPUNIT_ASSERT(aView2
.m_bViewCursorVisible
);
962 // Click on the shape in the second view.
963 aView1
.m_bViewCursorVisible
= true;
964 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
965 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
966 SdrObject
* pObject
= pPage
->GetObj(0);
967 Point aCenter
= pObject
->GetSnapRect().Center();
968 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN
, aCenter
.getX(), aCenter
.getY(), 1, MOUSE_LEFT
, 0);
969 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP
, aCenter
.getX(), aCenter
.getY(), 1, MOUSE_LEFT
, 0);
970 Scheduler::ProcessEventsToIdle();
971 // Make sure the "view/text" cursor of the first view gets a notification.
972 CPPUNIT_ASSERT(!aView1
.m_bViewCursorVisible
);
973 mxComponent
->dispose();
976 comphelper::LibreOfficeKit::setActive(false);
979 void SwTiledRenderingTest::testViewCursorCleanup()
981 comphelper::LibreOfficeKit::setActive();
983 // Load a document that has a shape and create two views.
984 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
986 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
987 int nView2
= SfxLokHelper::createView();
988 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
990 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
992 // Click on the shape in the second view.
993 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
994 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
995 SdrObject
* pObject
= pPage
->GetObj(0);
996 Point aCenter
= pObject
->GetSnapRect().Center();
997 aView1
.m_bGraphicViewSelection
= false;
998 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN
, aCenter
.getX(), aCenter
.getY(), 1, MOUSE_LEFT
, 0);
999 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP
, aCenter
.getX(), aCenter
.getY(), 1, MOUSE_LEFT
, 0);
1000 Scheduler::ProcessEventsToIdle();
1001 // Make sure there is a graphic view selection on the first view.
1002 CPPUNIT_ASSERT(aView1
.m_bGraphicViewSelection
);
1004 // Now destroy the second view.
1005 SfxLokHelper::destroyView(nView2
);
1006 Scheduler::ProcessEventsToIdle();
1007 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), SfxLokHelper::getViewsCount());
1008 // Make sure that the graphic view selection on the first view is cleaned up.
1009 CPPUNIT_ASSERT(!aView1
.m_bGraphicViewSelection
);
1010 mxComponent
->dispose();
1011 mxComponent
.clear();
1013 comphelper::LibreOfficeKit::setActive(false);
1016 void SwTiledRenderingTest::testViewLock()
1018 comphelper::LibreOfficeKit::setActive();
1020 // Load a document that has a shape and create two views.
1021 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
1022 ViewCallback aView1
;
1023 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1024 SfxLokHelper::createView();
1025 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1026 ViewCallback aView2
;
1027 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
1029 // Begin text edit in the second view and assert that the first gets a lock
1031 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1032 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1033 SdrObject
* pObject
= pPage
->GetObj(0);
1034 SdrView
* pView
= pWrtShell
->GetDrawView();
1035 aView1
.m_bViewLock
= false;
1036 pWrtShell
->GetView().BeginTextEdit(pObject
, pView
->GetSdrPageView(), pWrtShell
->GetWin());
1037 CPPUNIT_ASSERT(aView1
.m_bViewLock
);
1039 // End text edit in the second view, and assert that the lock is removed in
1041 pWrtShell
->EndTextEdit();
1042 CPPUNIT_ASSERT(!aView1
.m_bViewLock
);
1044 mxComponent
->dispose();
1045 mxComponent
.clear();
1047 comphelper::LibreOfficeKit::setActive(false);
1050 void SwTiledRenderingTest::testTextEditViewInvalidations()
1052 // Load a document that has a shape and create two views.
1053 comphelper::LibreOfficeKit::setActive();
1054 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
1055 ViewCallback aView1
;
1056 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1057 SfxLokHelper::createView();
1058 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1059 ViewCallback aView2
;
1060 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
1062 // Begin text edit in the second view.
1063 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1064 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1065 SdrObject
* pObject
= pPage
->GetObj(0);
1066 SdrView
* pView
= pWrtShell
->GetDrawView();
1067 pWrtShell
->GetView().BeginTextEdit(pObject
, pView
->GetSdrPageView(), pWrtShell
->GetWin());
1068 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1069 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1071 // Assert that both views are invalidated when pressing a key while in text edit.
1072 aView1
.m_bTilesInvalidated
= false;
1073 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'y', 0);
1074 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'y', 0);
1075 CPPUNIT_ASSERT(aView1
.m_bTilesInvalidated
);
1077 pWrtShell
->EndTextEdit();
1078 mxComponent
->dispose();
1079 mxComponent
.clear();
1080 comphelper::LibreOfficeKit::setActive(false);
1083 void SwTiledRenderingTest::testUndoInvalidations()
1085 // Load a document and create two views.
1086 comphelper::LibreOfficeKit::setActive();
1087 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1088 ViewCallback aView1
;
1089 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1090 int nView1
= SfxLokHelper::getView();
1091 SfxLokHelper::createView();
1092 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1093 ViewCallback aView2
;
1094 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
1095 SfxLokHelper::setView(nView1
);
1097 // Insert a character the end of the document.
1098 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1099 pWrtShell
->EndDoc();
1100 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'c', 0);
1101 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'c', 0);
1102 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
1103 CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb.c"), pShellCursor
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText());
1105 // Undo and assert that both views are invalidated.
1106 aView1
.m_bTilesInvalidated
= false;
1107 aView2
.m_bTilesInvalidated
= false;
1108 comphelper::dispatchCommand(".uno:Undo", {});
1109 Scheduler::ProcessEventsToIdle();
1110 CPPUNIT_ASSERT(aView1
.m_bTilesInvalidated
);
1111 // Undo was dispatched on the first view, this second view was not invalidated.
1112 CPPUNIT_ASSERT(aView2
.m_bTilesInvalidated
);
1114 mxComponent
->dispose();
1115 mxComponent
.clear();
1116 comphelper::LibreOfficeKit::setActive(false);
1119 void SwTiledRenderingTest::testUndoLimiting()
1121 // Load a document and create two views.
1122 comphelper::LibreOfficeKit::setActive();
1123 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1124 SwWrtShell
* pWrtShell1
= pXTextDocument
->GetDocShell()->GetWrtShell();
1125 SfxLokHelper::createView();
1126 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1128 // Insert a character the end of the document in the second view.
1129 SwWrtShell
* pWrtShell2
= pXTextDocument
->GetDocShell()->GetWrtShell();
1130 pWrtShell2
->EndDoc();
1131 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'c', 0);
1132 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'c', 0);
1133 SwShellCursor
* pShellCursor
= pWrtShell2
->getShellCursor(false);
1134 CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb.c"), pShellCursor
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText());
1136 // Assert that the first view can't undo, but the second view can.
1137 CPPUNIT_ASSERT(!pWrtShell1
->GetLastUndoInfo(nullptr, nullptr, &pWrtShell1
->GetView()));
1138 CPPUNIT_ASSERT(pWrtShell2
->GetLastUndoInfo(nullptr, nullptr, &pWrtShell2
->GetView()));
1140 comphelper::LibreOfficeKit::setActive(false);
1143 void SwTiledRenderingTest::testUndoShapeLimiting()
1145 // Load a document and create a view.
1146 comphelper::LibreOfficeKit::setActive();
1147 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
1148 SwWrtShell
* pWrtShell1
= pXTextDocument
->GetDocShell()->GetWrtShell();
1149 SfxLokHelper::createView();
1150 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1151 SwWrtShell
* pWrtShell2
= pXTextDocument
->GetDocShell()->GetWrtShell();
1153 // Start shape text in the second view.
1154 SdrPage
* pPage
= pWrtShell2
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1155 SdrObject
* pObject
= pPage
->GetObj(0);
1156 SdrView
* pView
= pWrtShell2
->GetDrawView();
1157 pWrtShell2
->GetView().BeginTextEdit(pObject
, pView
->GetSdrPageView(), pWrtShell2
->GetWin());
1158 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1159 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1161 // Assert that the first view can't and the second view can undo the insertion.
1162 SwDoc
* pDoc
= pXTextDocument
->GetDocShell()->GetDoc();
1163 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1164 rUndoManager
.SetView(&pWrtShell1
->GetView());
1165 // This was 1: first view could undo the change of the second view.
1166 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rUndoManager
.GetUndoActionCount());
1167 rUndoManager
.SetView(&pWrtShell2
->GetView());
1168 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager
.GetUndoActionCount());
1170 pWrtShell2
->EndTextEdit();
1171 rUndoManager
.SetView(nullptr);
1172 comphelper::LibreOfficeKit::setActive(false);
1175 void SwTiledRenderingTest::testUndoDispatch()
1177 // Load a document and create two views.
1178 comphelper::LibreOfficeKit::setActive();
1179 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1180 int nView1
= SfxLokHelper::getView();
1181 SfxLokHelper::createView();
1182 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1183 int nView2
= SfxLokHelper::getView();
1185 // Insert a character in the first view.
1186 SfxLokHelper::setView(nView1
);
1187 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'c', 0);
1188 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'c', 0);
1190 // Click before the first word in the second view.
1191 SfxLokHelper::setView(nView2
);
1192 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1193 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
1194 Point aStart
= pShellCursor
->GetSttPos();
1195 aStart
.setX(aStart
.getX() - 1000);
1196 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN
, aStart
.getX(), aStart
.getY(), 1, MOUSE_LEFT
, 0);
1197 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP
, aStart
.getX(), aStart
.getY(), 1, MOUSE_LEFT
, 0);
1198 uno::Reference
<frame::XDesktop2
> xDesktop
= frame::Desktop::create(comphelper::getProcessComponentContext());
1199 uno::Reference
<frame::XFrame
> xFrame2
= xDesktop
->getActiveFrame();
1201 // Now switch back to the first view, and make sure that the active frame is updated.
1202 SfxLokHelper::setView(nView1
);
1203 uno::Reference
<frame::XFrame
> xFrame1
= xDesktop
->getActiveFrame();
1204 // This failed: setView() did not update the active frame.
1205 CPPUNIT_ASSERT(xFrame1
!= xFrame2
);
1207 comphelper::LibreOfficeKit::setActive(false);
1210 void SwTiledRenderingTest::testUndoRepairDispatch()
1212 // Load a document and create two views.
1213 comphelper::LibreOfficeKit::setActive();
1214 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1215 int nView1
= SfxLokHelper::getView();
1216 SfxLokHelper::createView();
1217 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1218 int nView2
= SfxLokHelper::getView();
1220 // Insert a character in the first view.
1221 SfxLokHelper::setView(nView1
);
1222 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'c', 0);
1223 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'c', 0);
1225 // Assert that by default the second view can't undo the action.
1226 SfxLokHelper::setView(nView2
);
1227 SwDoc
* pDoc
= pXTextDocument
->GetDocShell()->GetDoc();
1228 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1229 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager
.GetUndoActionCount());
1230 comphelper::dispatchCommand(".uno:Undo", {});
1231 Scheduler::ProcessEventsToIdle();
1232 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager
.GetUndoActionCount());
1234 // But the same is allowed in repair mode.
1235 SfxLokHelper::setView(nView2
);
1236 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager
.GetUndoActionCount());
1237 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
1239 {"Repair", uno::makeAny(true)}
1241 comphelper::dispatchCommand(".uno:Undo", aPropertyValues
);
1242 Scheduler::ProcessEventsToIdle();
1243 // This was 1: repair mode couldn't undo the action, either.
1244 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rUndoManager
.GetUndoActionCount());
1246 comphelper::LibreOfficeKit::setActive(false);
1249 void SwTiledRenderingTest::testShapeTextUndoShells()
1251 // Load a document and create a view.
1252 comphelper::LibreOfficeKit::setActive();
1253 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
1254 sal_Int32 nView1
= SfxLokHelper::getView();
1257 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1258 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1259 SdrObject
* pObject
= pPage
->GetObj(0);
1260 SdrView
* pView
= pWrtShell
->GetDrawView();
1261 pWrtShell
->GetView().BeginTextEdit(pObject
, pView
->GetSdrPageView(), pWrtShell
->GetWin());
1262 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1263 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1265 // Make sure that the undo item remembers who created it.
1266 SwDoc
* pDoc
= pXTextDocument
->GetDocShell()->GetDoc();
1267 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1268 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager
.GetUndoActionCount());
1269 // This was -1: the view shell id for the undo action wasn't known.
1270 CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1
), rUndoManager
.GetUndoAction()->GetViewShellId());
1272 mxComponent
->dispose();
1273 mxComponent
.clear();
1274 comphelper::LibreOfficeKit::setActive(false);
1277 void SwTiledRenderingTest::testShapeTextUndoGroupShells()
1279 // Load a document and create a view.
1280 comphelper::LibreOfficeKit::setActive();
1281 SwXTextDocument
* pXTextDocument
= createDoc("shape.fodt");
1282 ViewCallback aView1
;
1283 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1284 sal_Int32 nView1
= SfxLokHelper::getView();
1287 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1288 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1289 SdrObject
* pObject
= pPage
->GetObj(0);
1290 SdrView
* pView
= pWrtShell
->GetDrawView();
1291 pWrtShell
->GetView().BeginTextEdit(pObject
, pView
->GetSdrPageView(), pWrtShell
->GetWin());
1292 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1293 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1294 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, awt::Key::BACKSPACE
);
1295 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, awt::Key::BACKSPACE
);
1297 // Make sure that the undo item remembers who created it.
1298 SwDoc
* pDoc
= pXTextDocument
->GetDocShell()->GetDoc();
1299 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1300 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rUndoManager
.GetUndoActionCount());
1301 // This was -1: the view shell id for the (top) undo list action wasn't known.
1302 CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1
), rUndoManager
.GetUndoAction()->GetViewShellId());
1304 // Create an editeng text selection in the first view.
1305 EditView
& rEditView
= pView
->GetTextEditOutlinerView()->GetEditView();
1306 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1307 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1308 // 0th para, 0th char -> 0th para, 1st char.
1309 ESelection
aWordSelection(0, 0, 0, 1);
1310 rEditView
.SetSelection(aWordSelection
);
1312 // Create a second view, and make sure that the new view sees the same
1313 // cursor position as the old one.
1314 SfxLokHelper::createView();
1315 pXTextDocument
->initializeForTiledRendering({});
1316 ViewCallback aView2
;
1317 aView2
.m_aViewCursor
= tools::Rectangle();
1318 aView2
.m_bViewSelectionSet
= false;
1319 aView2
.m_bViewLock
= false;
1320 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
1321 // Difference was 935 twips, the new view didn't see the editeng cursor of
1322 // the old one. The new difference should be <1px, but here we deal with twips.
1323 CPPUNIT_ASSERT(std::abs(aView1
.m_aOwnCursor
.Top() - aView2
.m_aViewCursor
.Top()) < 10);
1324 // This was false, editeng text selection of the first view wasn't noticed
1325 // by the second view.
1326 CPPUNIT_ASSERT(aView2
.m_bViewSelectionSet
);
1327 // This was false, the new view wasn't aware of the shape text lock created
1329 CPPUNIT_ASSERT(aView2
.m_bViewLock
);
1331 mxComponent
->dispose();
1332 mxComponent
.clear();
1333 comphelper::LibreOfficeKit::setActive(false);
1336 void SwTiledRenderingTest::testTrackChanges()
1339 comphelper::LibreOfficeKit::setActive();
1340 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1342 // Turn on trak changes, type "zzz" at the end, and move to the start.
1343 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1344 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1346 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1347 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView
);
1348 pWrtShell
->EndDoc();
1349 pWrtShell
->Insert("zzz");
1350 pWrtShell
->SttDoc();
1352 // Get the redline just created
1353 const SwRedlineTable
& rTable
= pWrtShell
->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable();
1354 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(1), rTable
.size());
1355 SwRangeRedline
* pRedline
= rTable
[0];
1357 // Reject the change by id, while the cursor does not cover the tracked change.
1358 uno::Sequence
<beans::PropertyValue
> aPropertyValues(comphelper::InitPropertySequence(
1360 {"RejectTrackedChange", uno::makeAny(static_cast<sal_uInt16
>(pRedline
->GetId()))}
1362 comphelper::dispatchCommand(".uno:RejectTrackedChange", aPropertyValues
);
1363 Scheduler::ProcessEventsToIdle();
1365 // Assert that the reject was performed.
1366 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
1367 // This was 'Aaa bbb.zzz', the change wasn't rejected.
1368 CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb."), pShellCursor
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText());
1370 comphelper::LibreOfficeKit::setActive(false);
1373 void SwTiledRenderingTest::testTrackChangesCallback()
1376 comphelper::LibreOfficeKit::setActive();
1377 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1378 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1379 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
1381 // Turn on track changes and type "x".
1382 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1383 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1384 m_nRedlineTableSizeChanged
= 0;
1385 pWrtShell
->Insert("x");
1387 // Assert that we get exactly one notification about the redline insert.
1388 // This was 0, as LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED wasn't sent.
1389 CPPUNIT_ASSERT_EQUAL(1, m_nRedlineTableSizeChanged
);
1391 CPPUNIT_ASSERT_EQUAL(-1, m_nTrackedChangeIndex
);
1392 pWrtShell
->Left(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1393 SfxItemSet
aSet(pWrtShell
->GetDoc()->GetAttrPool(), svl::Items
<FN_REDLINE_ACCEPT_DIRECT
, FN_REDLINE_ACCEPT_DIRECT
>{});
1394 SfxVoidItem
aItem(FN_REDLINE_ACCEPT_DIRECT
);
1396 pWrtShell
->GetView().GetState(aSet
);
1397 // This failed, LOK_CALLBACK_STATE_CHANGED wasn't sent.
1398 CPPUNIT_ASSERT_EQUAL(0, m_nTrackedChangeIndex
);
1400 comphelper::LibreOfficeKit::setActive(false);
1403 void SwTiledRenderingTest::testRedlineUpdateCallback()
1406 comphelper::LibreOfficeKit::setActive();
1407 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1408 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1409 pWrtShell
->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback
, this);
1411 // Turn on track changes, type "xx" and delete the second one.
1412 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1413 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1414 pWrtShell
->Insert("xx");
1415 m_nRedlineTableEntryModified
= 0;
1416 pWrtShell
->DelLeft();
1418 // Assert that we get exactly one notification about the redline update.
1419 // This was 0, as LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED wasn't sent.
1420 CPPUNIT_ASSERT_EQUAL(1, m_nRedlineTableEntryModified
);
1422 // Turn off the change tracking mode, make some modification to left of the
1423 // redline so that its position changes
1424 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(false));
1425 pWrtShell
->Left(CRSR_SKIP_CHARS
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1426 pWrtShell
->Insert("This text is left of the redline");
1428 // Position of the redline has changed => Modify callback
1429 CPPUNIT_ASSERT_EQUAL(2, m_nRedlineTableEntryModified
);
1431 pWrtShell
->DelLeft();
1432 // Deletion also emits Modify callback
1433 CPPUNIT_ASSERT_EQUAL(3, m_nRedlineTableEntryModified
);
1435 // Make changes to the right of the redline => no position change in redline
1436 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 100/*Go enough right */, /*bBasicCall=*/false);
1437 pWrtShell
->Insert("This text is right of the redline");
1439 // No Modify callbacks
1440 CPPUNIT_ASSERT_EQUAL(3, m_nRedlineTableEntryModified
);
1442 comphelper::LibreOfficeKit::setActive(false);
1445 void SwTiledRenderingTest::testSetViewGraphicSelection()
1448 comphelper::LibreOfficeKit::setActive();
1449 SwXTextDocument
* pXTextDocument
= createDoc("frame.odt");
1450 int nView1
= SfxLokHelper::getView();
1451 ViewCallback aView1
;
1452 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1453 // Create a second view, and switch back to the first view.
1454 SfxLokHelper::createView();
1455 pXTextDocument
->initializeForTiledRendering({});
1456 SfxLokHelper::setView(nView1
);
1458 // Mark the textframe in the first view.
1459 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1460 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1461 SdrObject
* pObject
= pPage
->GetObj(0);
1462 SdrView
* pView
= pWrtShell
->GetDrawView();
1463 pView
->MarkObj(pObject
, pView
->GetSdrPageView());
1464 CPPUNIT_ASSERT(aView1
.m_bGraphicSelection
);
1466 // Now start to switch to the second view (part of setView()).
1467 pWrtShell
->ShellLoseFocus();
1468 // This failed, mark handles were hidden in the first view.
1469 CPPUNIT_ASSERT(!pView
->areMarkHandlesHidden());
1471 mxComponent
->dispose();
1472 mxComponent
.clear();
1473 comphelper::LibreOfficeKit::setActive(false);
1476 void SwTiledRenderingTest::testCreateViewGraphicSelection()
1479 comphelper::LibreOfficeKit::setActive();
1480 SwXTextDocument
* pXTextDocument
= createDoc("frame.odt");
1481 ViewCallback aView1
;
1482 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1484 // Mark the textframe in the first view.
1485 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1486 SdrPage
* pPage
= pWrtShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
1487 SdrObject
* pObject
= pPage
->GetObj(0);
1488 SdrView
* pView
= pWrtShell
->GetDrawView();
1489 aView1
.m_bGraphicSelection
= true;
1490 pView
->MarkObj(pObject
, pView
->GetSdrPageView());
1491 pWrtShell
->HideCursor();
1492 CPPUNIT_ASSERT(aView1
.m_bGraphicSelection
);
1494 // Create a second view.
1495 SfxLokHelper::createView();
1496 // This was false, creating a second view cleared the selection of the
1498 CPPUNIT_ASSERT(aView1
.m_bGraphicSelection
);
1500 // Make sure that the hidden text cursor isn't visible in the second view, either.
1501 ViewCallback aView2
;
1502 aView2
.m_bViewCursorVisible
= true;
1503 aView2
.m_bGraphicViewSelection
= false;
1504 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
1505 // This was true, the second view didn't get the visibility of the text
1506 // cursor of the first view.
1507 CPPUNIT_ASSERT(!aView2
.m_bViewCursorVisible
);
1508 // This was false, the second view didn't get the graphic selection of the
1510 CPPUNIT_ASSERT(aView2
.m_bGraphicViewSelection
);
1512 mxComponent
->dispose();
1513 mxComponent
.clear();
1514 comphelper::LibreOfficeKit::setActive(false);
1517 void SwTiledRenderingTest::testCreateViewTextSelection()
1520 comphelper::LibreOfficeKit::setActive();
1521 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1522 ViewCallback aView1
;
1523 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1525 // Create a text selection:
1526 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1527 // Move the cursor into the second word.
1528 pWrtShell
->Right(CRSR_SKIP_CHARS
, /*bSelect=*/false, 5, /*bBasicCall=*/false);
1529 // Create a selection on the word.
1530 pWrtShell
->SelWrd();
1531 SwShellCursor
* pShellCursor
= pWrtShell
->getShellCursor(false);
1532 // Did we indeed manage to select the second word?
1533 CPPUNIT_ASSERT_EQUAL(OUString("bbb"), pShellCursor
->GetText());
1535 // Create a second view.
1536 SfxLokHelper::createView();
1538 // Make sure that the text selection is visible in the second view.
1539 ViewCallback aView2
;
1540 aView2
.m_bViewSelectionSet
= true;
1541 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
1542 // This failed, the second view didn't get the text selection of the first view.
1543 CPPUNIT_ASSERT(!aView2
.m_aViewSelection
.isEmpty());
1545 mxComponent
->dispose();
1546 mxComponent
.clear();
1547 comphelper::LibreOfficeKit::setActive(false);
1550 void SwTiledRenderingTest::testRedlineColors()
1553 comphelper::LibreOfficeKit::setActive();
1554 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1556 // Turn on track changes, type "zzz" at the end.
1557 uno::Reference
<beans::XPropertySet
> xPropertySet(mxComponent
, uno::UNO_QUERY
);
1558 xPropertySet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1559 SwWrtShell
* pWrtShell
= pXTextDocument
->GetDocShell()->GetWrtShell();
1560 pWrtShell
->EndDoc();
1561 pWrtShell
->Insert("zzz");
1563 // Assert that info about exactly one author is returned.
1564 OUString aInfo
= pXTextDocument
->getTrackedChangeAuthors();
1565 std::stringstream
aStream(aInfo
.toUtf8().getStr());
1566 boost::property_tree::ptree aTree
;
1567 boost::property_tree::read_json(aStream
, aTree
);
1568 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aTree
.get_child("authors").size());
1570 comphelper::LibreOfficeKit::setActive(false);
1573 void SwTiledRenderingTest::testCommentEndTextEdit()
1575 // Create a document, type a character and remember the cursor position.
1576 comphelper::LibreOfficeKit::setActive();
1577 SwXTextDocument
* pXTextDocument
= createDoc();
1578 ViewCallback aView1
;
1579 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1580 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1581 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1582 tools::Rectangle aBodyCursor
= aView1
.m_aOwnCursor
;
1584 // Create a comment and type a character there as well.
1585 const int nCtrlAltC
= KEY_MOD1
+ KEY_MOD2
+ 512 + 'c' - 'a';
1586 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'c', nCtrlAltC
);
1587 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'c', nCtrlAltC
);
1588 Scheduler::ProcessEventsToIdle();
1589 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'x', 0);
1590 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'x', 0);
1592 // End comment text edit by clicking in the body text area, and assert that
1593 // no unexpected cursor callbacks are emitted at origin (top left corner of
1595 aView1
.m_bOwnCursorAtOrigin
= false;
1596 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN
, aBodyCursor
.getX(), aBodyCursor
.getY(), 1, MOUSE_LEFT
, 0);
1597 pXTextDocument
->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP
, aBodyCursor
.getX(), aBodyCursor
.getY(), 1, MOUSE_LEFT
, 0);
1598 // This failed, the cursor was at 0, 0 at some point during end text edit
1600 CPPUNIT_ASSERT(!aView1
.m_bOwnCursorAtOrigin
);
1602 // Hit enter and expect invalidation.
1603 Scheduler::ProcessEventsToIdle();
1604 aView1
.m_bTilesInvalidated
= false;
1605 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
1606 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_RETURN
);
1607 Scheduler::ProcessEventsToIdle();
1608 CPPUNIT_ASSERT(aView1
.m_bTilesInvalidated
);
1610 mxComponent
->dispose();
1611 mxComponent
.clear();
1612 comphelper::LibreOfficeKit::setActive(false);
1615 void SwTiledRenderingTest::testCursorPosition()
1617 // Load a document and register a callback, should get an own cursor.
1618 comphelper::LibreOfficeKit::setActive();
1619 SwXTextDocument
* pXTextDocument
= createDoc();
1620 ViewCallback aView1
;
1621 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1623 // Crete a second view, so the first view gets a collaborative cursor.
1624 SfxLokHelper::createView();
1625 pXTextDocument
->initializeForTiledRendering({});
1626 ViewCallback aView2
;
1627 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView2
);
1629 // Make sure the two are exactly the same.
1630 // This failed, own cursor was at '1418, 1418', collaborative cursor was at
1631 // '1425, 1425', due to pixel alignment.
1632 CPPUNIT_ASSERT_EQUAL(aView1
.m_aOwnCursor
.toString(), aView1
.m_aViewCursor
.toString());
1634 mxComponent
->dispose();
1635 mxComponent
.clear();
1636 comphelper::LibreOfficeKit::setActive(false);
1639 void SwTiledRenderingTest::testPaintCallbacks()
1641 // Test that paintTile() never results in callbacks, which can cause a
1642 // paint <-> invalidate loop.
1644 // Load a document and register a callback for the first view.
1645 comphelper::LibreOfficeKit::setActive();
1646 SwXTextDocument
* pXTextDocument
= createDoc();
1647 ViewCallback aView1
;
1648 SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback
, &aView1
);
1650 // Create a second view and paint a tile on that second view.
1651 SfxLokHelper::createView();
1652 int nCanvasWidth
= 256;
1653 int nCanvasHeight
= 256;
1654 std::vector
<unsigned char> aBuffer(nCanvasWidth
* nCanvasHeight
* 4);
1655 ScopedVclPtrInstance
<VirtualDevice
> pDevice(nullptr, Size(1, 1), DeviceFormat::DEFAULT
);
1656 pDevice
->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth
, nCanvasHeight
), Fraction(1.0), Point(), aBuffer
.data());
1657 // Make sure that painting a tile in the second view doesn't invoke
1658 // callbacks on the first view.
1659 aView1
.m_bCalled
= false;
1660 pXTextDocument
->paintTile(*pDevice
.get(), nCanvasWidth
, nCanvasHeight
, /*nTilePosX=*/0, /*nTilePosY=*/0, /*nTileWidth=*/3840, /*nTileHeight=*/3840);
1661 CPPUNIT_ASSERT(!aView1
.m_bCalled
);
1663 mxComponent
->dispose();
1664 mxComponent
.clear();
1665 comphelper::LibreOfficeKit::setActive(false);
1668 void SwTiledRenderingTest::testUndoRepairResult()
1670 // Load a document and create two views.
1671 comphelper::LibreOfficeKit::setActive();
1672 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1673 int nView1
= SfxLokHelper::getView();
1674 SfxLokHelper::createView();
1675 TestResultListener
* pResult2
= new TestResultListener();
1676 css::uno::Reference
< css::frame::XDispatchResultListener
> xListener(static_cast< css::frame::XDispatchResultListener
* >(pResult2
), css::uno::UNO_QUERY
);
1677 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1678 int nView2
= SfxLokHelper::getView();
1680 // Insert a character in the second view.
1681 SfxLokHelper::setView(nView2
);
1682 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'b', 0);
1683 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'b', 0);
1685 // Insert a character in the first view.
1686 SfxLokHelper::setView(nView1
);
1687 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'a', 0);
1688 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'a', 0);
1690 // Assert that by default the second view can't undo the action.
1691 SfxLokHelper::setView(nView2
);
1692 comphelper::dispatchCommand(".uno:Undo", {}, xListener
);
1693 Scheduler::ProcessEventsToIdle();
1694 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(SID_REPAIRPACKAGE
), pResult2
->m_nDocRepair
);
1696 mxComponent
->dispose();
1697 mxComponent
.clear();
1698 comphelper::LibreOfficeKit::setActive(false);
1701 void SwTiledRenderingTest::testRedoRepairResult()
1703 // Load a document and create two views.
1704 comphelper::LibreOfficeKit::setActive();
1705 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1706 int nView1
= SfxLokHelper::getView();
1707 SfxLokHelper::createView();
1708 TestResultListener
* pResult2
= new TestResultListener();
1709 css::uno::Reference
< css::frame::XDispatchResultListener
> xListener(static_cast< css::frame::XDispatchResultListener
* >(pResult2
), css::uno::UNO_QUERY
);
1710 pXTextDocument
->initializeForTiledRendering(uno::Sequence
<beans::PropertyValue
>());
1711 int nView2
= SfxLokHelper::getView();
1713 // Insert a character in the second view.
1714 SfxLokHelper::setView(nView2
);
1715 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'b', 0);
1716 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'b', 0);
1718 // Insert a character in the first view.
1719 SfxLokHelper::setView(nView1
);
1720 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'a', 0);
1721 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'a', 0);
1722 comphelper::dispatchCommand(".uno:Undo", {}, xListener
);
1723 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(0), pResult2
->m_nDocRepair
);
1725 // Assert that by default the second view can't redo the action.
1726 SfxLokHelper::setView(nView2
);
1727 comphelper::dispatchCommand(".uno:Redo", {}, xListener
);
1728 Scheduler::ProcessEventsToIdle();
1729 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(SID_REPAIRPACKAGE
), pResult2
->m_nDocRepair
);
1731 mxComponent
->dispose();
1732 mxComponent
.clear();
1733 comphelper::LibreOfficeKit::setActive(false);
1738 void checkUndoRepairStates(SwXTextDocument
* pXTextDocument
, SwView
* pView1
, SwView
* pView2
)
1740 SfxItemSet
aItemSet1(pXTextDocument
->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1741 SfxItemSet
aItemSet2(pXTextDocument
->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1742 // first view, undo enabled
1743 pView1
->GetState(aItemSet1
);
1744 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET
, aItemSet1
.GetItemState(SID_UNDO
));
1745 const SfxUInt32Item
*pUnsetItem
= dynamic_cast<const SfxUInt32Item
*>(aItemSet1
.GetItem(SID_UNDO
));
1746 CPPUNIT_ASSERT(!pUnsetItem
);
1747 // second view, undo conflict
1748 pView2
->GetState(aItemSet2
);
1749 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET
, aItemSet2
.GetItemState(SID_UNDO
));
1750 const SfxUInt32Item
* pUInt32Item
= dynamic_cast<const SfxUInt32Item
*>(aItemSet2
.GetItem(SID_UNDO
));
1751 CPPUNIT_ASSERT(pUInt32Item
);
1752 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(SID_REPAIRPACKAGE
), pUInt32Item
->GetValue());
1757 void SwTiledRenderingTest::testDisableUndoRepair()
1759 comphelper::LibreOfficeKit::setActive();
1761 // Create two views.
1762 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1763 ViewCallback aView1
;
1764 SwView
* pView1
= dynamic_cast<SwView
*>(SfxViewShell::Current());
1765 CPPUNIT_ASSERT(pView1
);
1766 int nView1
= SfxLokHelper::getView();
1767 SfxLokHelper::createView();
1768 ViewCallback aView2
;
1769 SwView
* pView2
= dynamic_cast<SwView
*>(SfxViewShell::Current());
1770 CPPUNIT_ASSERT(pView2
);
1771 int nView2
= SfxLokHelper::getView();
1774 SfxItemSet
aItemSet1(pXTextDocument
->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1775 SfxItemSet
aItemSet2(pXTextDocument
->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1776 pView1
->GetState(aItemSet1
);
1777 CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED
, aItemSet1
.GetItemState(SID_UNDO
));
1778 pView2
->GetState(aItemSet2
);
1779 CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED
, aItemSet2
.GetItemState(SID_UNDO
));
1782 // Insert a character in the first view.
1783 SfxLokHelper::setView(nView1
);
1784 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'k', 0);
1785 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'k', 0);
1786 Scheduler::ProcessEventsToIdle();
1787 checkUndoRepairStates(pXTextDocument
, pView1
, pView2
);
1789 // Insert a character in the second view.
1790 SfxLokHelper::setView(nView2
);
1791 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'u', 0);
1792 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'u', 0);
1793 Scheduler::ProcessEventsToIdle();
1795 SfxItemSet
aItemSet1(pXTextDocument
->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1796 SfxItemSet
aItemSet2(pXTextDocument
->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items
<SID_UNDO
, SID_UNDO
>{});
1797 // second view, undo enabled
1798 pView2
->GetState(aItemSet2
);
1799 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET
, aItemSet2
.GetItemState(SID_UNDO
));
1800 const SfxUInt32Item
*pUnsetItem
= dynamic_cast<const SfxUInt32Item
*>(aItemSet2
.GetItem(SID_UNDO
));
1801 CPPUNIT_ASSERT(!pUnsetItem
);
1802 // first view, undo conflict
1803 pView1
->GetState(aItemSet1
);
1804 CPPUNIT_ASSERT_EQUAL(SfxItemState::SET
, aItemSet1
.GetItemState(SID_UNDO
));
1805 const SfxUInt32Item
* pUInt32Item
= dynamic_cast<const SfxUInt32Item
*>(aItemSet1
.GetItem(SID_UNDO
));
1806 CPPUNIT_ASSERT(pUInt32Item
);
1807 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(SID_REPAIRPACKAGE
), pUInt32Item
->GetValue());
1810 // Insert a character in the first view.
1811 SfxLokHelper::setView(nView1
);
1812 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'l', 0);
1813 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'l', 0);
1814 Scheduler::ProcessEventsToIdle();
1815 checkUndoRepairStates(pXTextDocument
, pView1
, pView2
);
1817 mxComponent
->dispose();
1818 mxComponent
.clear();
1819 comphelper::LibreOfficeKit::setActive(false);
1822 void SwTiledRenderingTest::testAllTrackedChanges()
1825 comphelper::LibreOfficeKit::setActive();
1826 createDoc("dummy.fodt");
1828 uno::Reference
<beans::XPropertySet
> xPropSet(mxComponent
, uno::UNO_QUERY
);
1829 xPropSet
->setPropertyValue("RecordChanges", uno::makeAny(true));
1832 SwView
* pView1
= dynamic_cast<SwView
*>(SfxViewShell::Current());
1833 CPPUNIT_ASSERT(pView1
);
1834 SwWrtShell
* pWrtShell1
= pView1
->GetWrtShellPtr();
1837 SfxLokHelper::createView();
1838 SwView
* pView2
= dynamic_cast<SwView
*>(SfxViewShell::Current());
1839 CPPUNIT_ASSERT(pView2
&& pView1
!= pView2
);
1840 SwWrtShell
* pWrtShell2
= pView2
->GetWrtShellPtr();
1841 // Insert text and reject all
1843 pWrtShell1
->SttDoc();
1844 pWrtShell1
->Insert("hxx");
1846 pWrtShell2
->EndDoc();
1847 pWrtShell2
->Insert("cxx");
1851 const SwRedlineTable
& rTable
= pWrtShell2
->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable();
1852 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(2), rTable
.size());
1854 SfxVoidItem
aItem(FN_REDLINE_REJECT_ALL
);
1855 pView1
->GetViewFrame()->GetDispatcher()->ExecuteList(FN_REDLINE_REJECT_ALL
,
1856 SfxCallMode::SYNCHRON
, { &aItem
});
1859 // The reject all was performed.
1860 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(0), rTable
.size());
1862 SwShellCursor
* pShellCursor
= pWrtShell1
->getShellCursor(false);
1863 CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb."), pShellCursor
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText());
1866 // Insert text and accept all
1868 pWrtShell1
->SttDoc();
1869 pWrtShell1
->Insert("hyy");
1871 pWrtShell2
->EndDoc();
1872 pWrtShell2
->Insert("cyy");
1875 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(2), rTable
.size());
1877 SfxVoidItem
aItem(FN_REDLINE_ACCEPT_ALL
);
1878 pView1
->GetViewFrame()->GetDispatcher()->ExecuteList(FN_REDLINE_ACCEPT_ALL
,
1879 SfxCallMode::SYNCHRON
, { &aItem
});
1882 // The accept all was performed
1883 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type
>(0), rTable
.size());
1885 SwShellCursor
* pShellCursor
= pWrtShell2
->getShellCursor(false);
1886 CPPUNIT_ASSERT_EQUAL(OUString("hyyAaa bbb.cyy"), pShellCursor
->GetPoint()->nNode
.GetNode().GetTextNode()->GetText());
1889 comphelper::LibreOfficeKit::setActive(false);
1892 void SwTiledRenderingTest::testDocumentRepair()
1894 comphelper::LibreOfficeKit::setActive();
1896 // Create two views.
1897 SwXTextDocument
* pXTextDocument
= createDoc("dummy.fodt");
1899 SfxViewShell
* pView1
= SfxViewShell::Current();
1902 SfxLokHelper::createView();
1903 SfxViewShell
* pView2
= SfxViewShell::Current();
1904 int nView2
= SfxLokHelper::getView();
1905 CPPUNIT_ASSERT(pView1
!= pView2
);
1907 std::unique_ptr
<SfxPoolItem
> pItem1
;
1908 std::unique_ptr
<SfxPoolItem
> pItem2
;
1909 pView1
->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR
, pItem1
);
1910 pView2
->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR
, pItem2
);
1911 CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem
* >(pItem1
.get()));
1912 CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem
* >(pItem2
.get()));
1913 CPPUNIT_ASSERT_EQUAL(false, dynamic_cast< const SfxBoolItem
* >(pItem1
.get())->GetValue());
1914 CPPUNIT_ASSERT_EQUAL(false, dynamic_cast< const SfxBoolItem
* >(pItem2
.get())->GetValue());
1917 // Insert a character in the second view.
1918 SfxLokHelper::setView(nView2
);
1919 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 'u', 0);
1920 pXTextDocument
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 'u', 0);
1921 Scheduler::ProcessEventsToIdle();
1923 std::unique_ptr
<SfxPoolItem
> pItem1
;
1924 std::unique_ptr
<SfxPoolItem
> pItem2
;
1925 pView1
->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR
, pItem1
);
1926 pView2
->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR
, pItem2
);
1927 CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem
* >(pItem1
.get()));
1928 CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem
* >(pItem2
.get()));
1929 CPPUNIT_ASSERT_EQUAL(true, dynamic_cast< const SfxBoolItem
* >(pItem1
.get())->GetValue());
1930 CPPUNIT_ASSERT_EQUAL(true, dynamic_cast< const SfxBoolItem
* >(pItem2
.get())->GetValue());
1933 comphelper::LibreOfficeKit::setActive(false);
1937 CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest
);
1939 CPPUNIT_PLUGIN_IMPLEMENT();
1941 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */