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/.
10 #include <test/lokcallback.hxx>
12 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
13 #include <rtl/strbuf.hxx>
14 #include <tools/gen.hxx>
15 #include <comphelper/lok.hxx>
16 #include <sfx2/viewsh.hxx>
17 #include <sfx2/childwin.hxx>
18 #include <sfx2/viewfrm.hxx>
19 #include <sfx2/sfxsids.hrc>
20 #include <sfx2/sidebar/SidebarDockingWindow.hxx>
22 TestLokCallbackWrapper::TestLokCallbackWrapper(LibreOfficeKitCallback callback
, void* data
)
23 : Idle("TestLokCallbackWrapper flush timer")
24 , m_callback(callback
)
27 // Flushing timer needs to run with the lowest priority, so that all pending tasks
28 // such as invalidations are processed before it.
29 SetPriority(TaskPriority::LOWEST
);
32 void TestLokCallbackWrapper::clear()
35 m_updatedTypes
.clear();
36 m_updatedTypesPerViewId
.clear();
39 inline void TestLokCallbackWrapper::startTimer()
45 constexpr int NO_VIEWID
= -1;
47 inline void TestLokCallbackWrapper::callCallback(int nType
, const char* pPayload
, int nViewId
)
49 discardUpdatedTypes(nType
, nViewId
);
50 m_callback(nType
, pPayload
, m_data
);
54 void TestLokCallbackWrapper::libreOfficeKitViewCallback(int nType
, const rtl::OString
& pPayload
)
56 callCallback(nType
, pPayload
.getStr(), NO_VIEWID
);
59 void TestLokCallbackWrapper::libreOfficeKitViewCallbackWithViewId(int nType
,
60 const rtl::OString
& pPayload
,
63 callCallback(nType
, pPayload
.getStr(), nViewId
);
66 void TestLokCallbackWrapper::libreOfficeKitViewInvalidateTilesCallback(
67 const tools::Rectangle
* pRect
, int nPart
, int nMode
)
69 OStringBuffer
buf(64);
71 buf
.append(pRect
->toString());
74 if (comphelper::LibreOfficeKit::isPartInInvalidation())
76 buf
.append(", " + OString::number(static_cast<sal_Int32
>(nPart
)) + ", "
77 + OString::number(static_cast<sal_Int32
>(nMode
)));
79 callCallback(LOK_CALLBACK_INVALIDATE_TILES
, buf
.makeStringAndClear().getStr(), NO_VIEWID
);
82 // TODO This is probably a pointless code duplication with CallbackFlushHandler,
83 // and using this in unittests also means that CallbackFlushHandler does not get
84 // tested as thoroughly as it could. On the other hand, this class is simpler,
85 // so debugging those unittests should also be simpler. The proper solution
86 // is presumably this class using CallbackFlushHandler internally by default,
87 // but having an option to use this simpler code when needed.
89 void TestLokCallbackWrapper::libreOfficeKitViewUpdatedCallback(int nType
)
91 if (std::find(m_updatedTypes
.begin(), m_updatedTypes
.end(), nType
) == m_updatedTypes
.end())
93 m_updatedTypes
.push_back(nType
);
98 void TestLokCallbackWrapper::libreOfficeKitViewUpdatedCallbackPerViewId(int nType
, int nViewId
,
101 const PerViewIdData data
{ nType
, nViewId
, nSourceViewId
};
102 auto& l
= m_updatedTypesPerViewId
;
103 // The source view doesn't matter for uniqueness, just keep the latest one.
104 auto it
= std::find_if(l
.begin(), l
.end(), [data
](const PerViewIdData
& other
) {
105 return data
.type
== other
.type
&& data
.viewId
== other
.viewId
;
114 void TestLokCallbackWrapper::libreOfficeKitViewAddPendingInvalidateTiles()
116 // Invoke() will call flushPendingLOKInvalidateTiles().
120 void TestLokCallbackWrapper::discardUpdatedTypes(int nType
, int nViewId
)
122 // If a callback is called directly with an event, drop the updated flag for it, since
123 // the direct event replaces it.
124 for (auto it
= m_updatedTypes
.begin(); it
!= m_updatedTypes
.end();)
127 it
= m_updatedTypes
.erase(it
);
131 // If we do not have a specific view id, drop flag for all views.
132 bool allViewIds
= false;
135 if (nType
== LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR
136 && !comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation())
138 for (auto it
= m_updatedTypesPerViewId
.begin(); it
!= m_updatedTypesPerViewId
.end();)
140 if (it
->type
== nType
&& (allViewIds
|| it
->viewId
== nViewId
))
141 it
= m_updatedTypesPerViewId
.erase(it
);
147 void TestLokCallbackWrapper::flushLOKData()
149 if (m_updatedTypes
.empty() && m_updatedTypesPerViewId
.empty())
151 // Ask for payloads of all the pending types that need updating, and call the generic callback with that data.
152 assert(m_viewId
>= 0);
153 SfxViewShell
* viewShell
= SfxViewShell::GetFirst(false, [this](const SfxViewShell
& shell
) {
154 return shell
.GetViewShellId().get() == m_viewId
;
156 assert(viewShell
!= nullptr);
157 // First move data to local structures, so that callbacks don't possibly modify it.
158 std::vector
<int> updatedTypes
;
159 std::swap(updatedTypes
, m_updatedTypes
);
160 std::vector
<PerViewIdData
> updatedTypesPerViewId
;
161 std::swap(updatedTypesPerViewId
, m_updatedTypesPerViewId
);
163 for (int type
: updatedTypes
)
165 std::optional
<OString
> payload
= viewShell
->getLOKPayload(type
, m_viewId
);
167 libreOfficeKitViewCallback(type
, *payload
);
169 for (const PerViewIdData
& data
: updatedTypesPerViewId
)
171 viewShell
= SfxViewShell::GetFirst(false, [data
](const SfxViewShell
& shell
) {
172 return shell
.GetViewShellId().get() == data
.sourceViewId
;
174 assert(viewShell
!= nullptr);
175 std::optional
<OString
> payload
= viewShell
->getLOKPayload(data
.type
, data
.viewId
);
177 libreOfficeKitViewCallbackWithViewId(data
.type
, *payload
, data
.viewId
);
181 void TestLokCallbackWrapper::Invoke()
183 // Timer timeout, flush any possibly pending data.
184 for (SfxViewShell
* viewShell
= SfxViewShell::GetFirst(false); viewShell
!= nullptr;
185 viewShell
= SfxViewShell::GetNext(*viewShell
, false))
187 viewShell
->flushPendingLOKInvalidateTiles();
192 SfxChildWindow
* TestLokCallbackWrapper::InitializeSidebar()
194 // in init.cxx we do setupSidebar which creates the controller, do it here
196 SfxViewShell
* pViewShell
= SfxViewShell::Current();
199 SfxViewFrame
& rViewFrame
= pViewShell
->GetViewFrame();
200 rViewFrame
.ShowChildWindow(SID_SIDEBAR
);
201 SfxChildWindow
* pSideBar
= rViewFrame
.GetChildWindow(SID_SIDEBAR
);
204 auto pDockingWin
= dynamic_cast<sfx2::sidebar::SidebarDockingWindow
*>(pSideBar
->GetWindow());
207 pDockingWin
->GetOrCreateSidebarController(); // just to create the controller
212 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */