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>
18 TestLokCallbackWrapper::TestLokCallbackWrapper(LibreOfficeKitCallback callback
, void* data
)
19 : Idle("TestLokCallbackWrapper flush timer")
20 , m_callback(callback
)
23 // Flushing timer needs to run with the lowest priority, so that all pending tasks
24 // such as invalidations are processed before it.
25 SetPriority(TaskPriority::LOWEST
);
28 void TestLokCallbackWrapper::clear()
31 m_updatedTypes
.clear();
32 m_updatedTypesPerViewId
.clear();
35 inline void TestLokCallbackWrapper::startTimer()
41 constexpr int NO_VIEWID
= -1;
43 inline void TestLokCallbackWrapper::callCallback(int nType
, const char* pPayload
, int nViewId
)
45 discardUpdatedTypes(nType
, nViewId
);
46 m_callback(nType
, pPayload
, m_data
);
50 void TestLokCallbackWrapper::libreOfficeKitViewCallback(int nType
, const rtl::OString
& pPayload
)
52 callCallback(nType
, pPayload
.getStr(), NO_VIEWID
);
55 void TestLokCallbackWrapper::libreOfficeKitViewCallbackWithViewId(int nType
,
56 const rtl::OString
& pPayload
,
59 callCallback(nType
, pPayload
.getStr(), nViewId
);
62 void TestLokCallbackWrapper::libreOfficeKitViewInvalidateTilesCallback(
63 const tools::Rectangle
* pRect
, int nPart
, int nMode
)
65 OStringBuffer
buf(64);
67 buf
.append(pRect
->toString());
70 if (comphelper::LibreOfficeKit::isPartInInvalidation())
72 buf
.append(", " + OString::number(static_cast<sal_Int32
>(nPart
)) + ", "
73 + OString::number(static_cast<sal_Int32
>(nMode
)));
75 callCallback(LOK_CALLBACK_INVALIDATE_TILES
, buf
.makeStringAndClear().getStr(), NO_VIEWID
);
78 // TODO This is probably a pointless code duplication with CallbackFlushHandler,
79 // and using this in unittests also means that CallbackFlushHandler does not get
80 // tested as thoroughly as it could. On the other hand, this class is simpler,
81 // so debugging those unittests should also be simpler. The proper solution
82 // is presumably this class using CallbackFlushHandler internally by default,
83 // but having an option to use this simpler code when needed.
85 void TestLokCallbackWrapper::libreOfficeKitViewUpdatedCallback(int nType
)
87 if (std::find(m_updatedTypes
.begin(), m_updatedTypes
.end(), nType
) == m_updatedTypes
.end())
89 m_updatedTypes
.push_back(nType
);
94 void TestLokCallbackWrapper::libreOfficeKitViewUpdatedCallbackPerViewId(int nType
, int nViewId
,
97 const PerViewIdData data
{ nType
, nViewId
, nSourceViewId
};
98 auto& l
= m_updatedTypesPerViewId
;
99 // The source view doesn't matter for uniqueness, just keep the latest one.
100 auto it
= std::find_if(l
.begin(), l
.end(), [data
](const PerViewIdData
& other
) {
101 return data
.type
== other
.type
&& data
.viewId
== other
.viewId
;
110 void TestLokCallbackWrapper::libreOfficeKitViewAddPendingInvalidateTiles()
112 // Invoke() will call flushPendingLOKInvalidateTiles().
116 void TestLokCallbackWrapper::discardUpdatedTypes(int nType
, int nViewId
)
118 // If a callback is called directly with an event, drop the updated flag for it, since
119 // the direct event replaces it.
120 for (auto it
= m_updatedTypes
.begin(); it
!= m_updatedTypes
.end();)
123 it
= m_updatedTypes
.erase(it
);
127 // If we do not have a specific view id, drop flag for all views.
128 bool allViewIds
= false;
131 if (nType
== LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR
132 && !comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation())
134 for (auto it
= m_updatedTypesPerViewId
.begin(); it
!= m_updatedTypesPerViewId
.end();)
136 if (it
->type
== nType
&& (allViewIds
|| it
->viewId
== nViewId
))
137 it
= m_updatedTypesPerViewId
.erase(it
);
143 void TestLokCallbackWrapper::flushLOKData()
145 if (m_updatedTypes
.empty() && m_updatedTypesPerViewId
.empty())
147 // Ask for payloads of all the pending types that need updating, and call the generic callback with that data.
148 assert(m_viewId
>= 0);
149 SfxViewShell
* viewShell
= SfxViewShell::GetFirst(false, [this](const SfxViewShell
* shell
) {
150 return shell
->GetViewShellId().get() == m_viewId
;
152 assert(viewShell
!= nullptr);
153 // First move data to local structures, so that callbacks don't possibly modify it.
154 std::vector
<int> updatedTypes
;
155 std::swap(updatedTypes
, m_updatedTypes
);
156 std::vector
<PerViewIdData
> updatedTypesPerViewId
;
157 std::swap(updatedTypesPerViewId
, m_updatedTypesPerViewId
);
159 for (int type
: updatedTypes
)
161 std::optional
<OString
> payload
= viewShell
->getLOKPayload(type
, m_viewId
);
163 libreOfficeKitViewCallback(type
, *payload
);
165 for (const PerViewIdData
& data
: updatedTypesPerViewId
)
167 viewShell
= SfxViewShell::GetFirst(false, [data
](const SfxViewShell
* shell
) {
168 return shell
->GetViewShellId().get() == data
.sourceViewId
;
170 assert(viewShell
!= nullptr);
171 std::optional
<OString
> payload
= viewShell
->getLOKPayload(data
.type
, data
.viewId
);
173 libreOfficeKitViewCallbackWithViewId(data
.type
, *payload
, data
.viewId
);
177 void TestLokCallbackWrapper::Invoke()
179 // Timer timeout, flush any possibly pending data.
180 for (SfxViewShell
* viewShell
= SfxViewShell::GetFirst(false); viewShell
!= nullptr;
181 viewShell
= SfxViewShell::GetNext(*viewShell
, false))
183 viewShell
->flushPendingLOKInvalidateTiles();
188 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */