Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohosclipboardobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qohosclipboardobject.h>
5
6#include <QtCore/private/qohoscommon_p.h>
7#include <QtCore/private/qohoslogger_p.h>
8#include <QtCore/qurl.h>
9#include <database/pasteboard/oh_pasteboard.h>
10#include <database/pasteboard/oh_pasteboard_err_code.h>
11#include <database/udmf/udmf.h>
12#include <database/udmf/uds.h>
13#include <memory>
14#include <multimedia/image_framework/image/image_common.h>
15#include <multimedia/image_framework/image/pixelmap_native.h>
16#include <qarkui/qarkuiutils.h>
17#include <qohosapppermissions_p.h>
18#include <qohosplugincore.h>
19#include <qohosudmfconversions.h>
20#include <qohosutils.h>
21
23
24namespace {
25
26const auto mimeTextPlain = QString::fromUtf8("text/plain");
27const auto mimeTextHtml = QString::fromUtf8("text/html");
28const auto mimeTextUriList = QString::fromUtf8("text/uri-list");
29const auto mimeAppXQtImage = QString::fromUtf8("application/x-qt-image");
30
35
36const char *getPasteboardNotifyTypeAsString(::Pasteboard_NotifyType notifyType)
37{
38 switch (notifyType) {
39 case ::Pasteboard_NotifyType::NOTIFY_LOCAL_DATA_CHANGE:
40 return "NOTIFY_LOCAL_DATA_CHANGE";
41 case ::Pasteboard_NotifyType::NOTIFY_REMOTE_DATA_CHANGE:
42 return "NOTIFY_REMOTE_DATA_CHANGE";
43 }
44 return "<illegal-Pasteboard_NotifyType>";
45}
46
48{
49 switch (dataSource) {
51 return "OurProcess";
53 return "OtherProcess";
54 }
55 return "<illegal-PasteboardDataSource>";
56}
57
59{
60 return std::shared_ptr<::OH_PasteboardObserver>(
61 QArkUi::callArkUiOrFailOnNullResult(
62 Q_OHOS_NAMED_FUNC(::OH_PasteboardObserver_Create)),
63 [](auto *pasteboardDataObserver) {
64 int observerDestroyRes = QArkUi::callArkUi(
65 Q_OHOS_NAMED_FUNC(::OH_PasteboardObserver_Destroy),
66 pasteboardDataObserver);
67 if (observerDestroyRes != ::PASTEBOARD_ErrCode::ERR_OK) {
68 qOhosPrintfError(
69 "%s: failed at destroying pasteboard observer.", Q_FUNC_INFO);
70 }
71 });
72}
73
75 std::shared_ptr<::OH_Pasteboard> pasteboard,
76 std::shared_ptr<::OH_PasteboardObserver> pasteboardObserver,
77 ::Pasteboard_NotifyType notifyType,
78 std::function<void()> dataChangedFunc)
79{
80 QArkUi::callArkUiOrFailOnErrorResult(
81 Q_OHOS_NAMED_FUNC(::OH_Pasteboard_Subscribe),
82 pasteboard.get(), notifyType, pasteboardObserver.get());
83
84 auto sharedDataChangedFunc = QtOhos::moveToSharedPtr(std::move(dataChangedFunc));
85
86 auto subscriptionHandle = QtOhos::makeDestroyNotifier(
87 [pasteboard, notifyType, pasteboardObserver, sharedDataChangedFunc]() {
88 int unsubscribeRes = QArkUi::callArkUi(
89 Q_OHOS_NAMED_FUNC(::OH_Pasteboard_Unsubscribe),
90 pasteboard.get(), notifyType, pasteboardObserver.get());
91 if (unsubscribeRes != ::PASTEBOARD_ErrCode::ERR_OK) {
92 qOhosPrintfError(
93 "%s: failed at unsubscribing from pasteboard %s.", Q_FUNC_INFO,
94 getPasteboardNotifyTypeAsString(notifyType));
95 }
96 });
97
98 QArkUi::callArkUiOrFailOnErrorResult(
99 Q_OHOS_NAMED_FUNC(::OH_PasteboardObserver_SetData),
100 pasteboardObserver.get(), sharedDataChangedFunc.get(),
101 [](void *ctx, ::Pasteboard_NotifyType) {
102 auto *dataChangedFunc = reinterpret_cast<std::function<void()> *>(ctx);
103 (*dataChangedFunc)();
104 },
105 [](void *) {});
106
107 return subscriptionHandle;
108}
109
111 std::shared_ptr<::OH_Pasteboard> pasteboard, std::function<void()> dataChangedListener,
112 std::vector<::Pasteboard_NotifyType> monitoredNotifyTypes)
113{
114 std::vector<std::shared_ptr<void>> subscriptionHandles;
115 auto sharedDataChangedFunc = QtOhos::moveToSharedPtr(std::move(dataChangedListener));
116
117 for (auto notifyType : monitoredNotifyTypes) {
118 auto observer = createPasteboardDataObserver();
119 subscriptionHandles.push_back(
120 subscribePasteboardObserver(
121 pasteboard, observer, notifyType,
122 [sharedDataChangedFunc]() {
123 (*sharedDataChangedFunc)();
124 }));
125 }
126
127 return QtOhos::moveToSharedPtr(std::move(subscriptionHandles));
128}
129
131{
132 if (!QArkUi::callArkUi(Q_OHOS_NAMED_FUNC(::OH_Pasteboard_HasData), pasteboard))
133 return nullptr;
134
135 int res;
136 auto *udmfDataPtr = QArkUi::callArkUi(
137 Q_OHOS_NAMED_FUNC(::OH_Pasteboard_GetData),
138 pasteboard, &res);
139
140 if (res != ::PASTEBOARD_ErrCode::ERR_OK || udmfDataPtr == nullptr) {
141 qOhosPrintfError("%s: error reading pasteboard data: %d / %p", Q_FUNC_INFO, res, udmfDataPtr);
142 return nullptr;
143 }
144
145 return std::make_unique<QOhosUdmfData>(QOhosUdmfData::takeOwnership(udmfDataPtr));
146}
147
148}
149
151 std::function<void(QOhosOptional<PasteboardDataSource>)> &&pasteboardUpdatesNotifier)
152{
154 [&](QtOhos::JsState &) {
155 m_pasteboard = std::shared_ptr<::OH_Pasteboard>(
156 QArkUi::callArkUiOrFailOnNullResult(
157 Q_OHOS_NAMED_FUNC(::OH_Pasteboard_Create)),
158 [](auto *pasteboard) {
159 QArkUi::callArkUi(Q_OHOS_NAMED_FUNC(::OH_Pasteboard_Destroy), pasteboard);
160 });
161 auto sharedPasteboardUpdatesNotifier = QtOhos::moveToSharedPtr(
162 std::move(pasteboardUpdatesNotifier));
163
164 auto pasteboardDataChangedJsThreadListener = std::make_shared<std::function<void()>>(
165 [this, weakPasteboardUpdatesNotifier = QtOhos::makeWeakPtr(sharedPasteboardUpdatesNotifier)]() {
166 auto optPasteboardUdmfData = tryGetUdmfDataFromPasteboard(m_pasteboard.get());
167 auto pasteboardDataSource =
168 optPasteboardUdmfData
169 ? makeQOhosOptional(
170 isQOhosUdmfDataConvertedFromThisProcessMimeData(*optPasteboardUdmfData)
174
175 qOhosPrintfDebug(
176 "%s: Pasteboard data source: %s",
177 Q_FUNC_INFO, pasteboardDataSource.transform(&getPasteboardDataSourceAsString).valueOr("<empty>"));
178
179 QtOhos::invokeInQtThread(
180 [weakPasteboardUpdatesNotifier, pasteboardDataSource]() {
181 auto sharedPasteboardUpdatesNotifier = weakPasteboardUpdatesNotifier.lock();
182 if (sharedPasteboardUpdatesNotifier)
183 (*sharedPasteboardUpdatesNotifier)(pasteboardDataSource);
184 });
185 });
186
187 m_pasteboardDataChangedListenerHandle = QtOhos::makeSharedPtrWithAttachedExtraData(
188 addPasteboardDataChangedListener(
189 m_pasteboard,
190 [pasteboardDataChangedJsThreadListener]() {
191 auto __dbg = make_QCScopedDebugJS(Q_FUNC_INFO);
192 QtOhos::invokeInJsThread(
193 [pasteboardDataChangedJsThreadListener](auto &) {
194 (*pasteboardDataChangedJsThreadListener)();
195 });
196 },
197 {
198 ::Pasteboard_NotifyType::NOTIFY_LOCAL_DATA_CHANGE,
199 ::Pasteboard_NotifyType::NOTIFY_REMOTE_DATA_CHANGE,
200 }),
201 sharedPasteboardUpdatesNotifier);
202 });
203}
204
205std::unique_ptr<QOhosClipboardObject> QOhosClipboardObject::makeInstance(
206 std::function<void(QOhosOptional<QOhosClipboardObject::PasteboardDataSource>)> &&pasteboardUpdatesNotifier)
207{
208 return std::unique_ptr<QOhosClipboardObject>(
209 new QOhosClipboardObject(std::move(pasteboardUpdatesNotifier)));
210}
211
213{
215 QOhosSupplier<std::unique_ptr<QMimeData>> mimeDataFactory;
216 std::tie(dataSource, mimeDataFactory) = QtOhos::evalInJsThreadWithConsumer<std::pair<QOhosOptional<PasteboardDataSource>, QOhosSupplier<std::unique_ptr<QMimeData>>>>(
217 [&](QtOhos::JsState &jsState, QOhosConsumer<std::pair<QOhosOptional<PasteboardDataSource>, QOhosSupplier<std::unique_ptr<QMimeData>>>> resultConsumer) {
218 static constexpr const char *ohosGetPasteboardDataPermission = "ohos.permission.READ_PASTEBOARD";
219 QOhosAppPermissions::checkAppPermissionGrantedWithConsumer(
220 jsState, ohosGetPasteboardDataPermission,
221 [this, resultConsumer = std::move(resultConsumer)](auto &, bool permissionGranted) {
222 if (!permissionGranted) {
223 qOhosPrintfError(
224 "%s: %s hasn't been granted by user. Cannot read pasteboard data.", Q_FUNC_INFO,
225 ohosGetPasteboardDataPermission);
226 resultConsumer({{}, std::make_unique<QMimeData>});
227 return;
228 }
229
230 auto optPasteboardUdmfData = tryGetUdmfDataFromPasteboard(m_pasteboard.get());
231 if (!optPasteboardUdmfData) {
232 resultConsumer({{}, std::make_unique<QMimeData>});
233 return;
234 }
235
236 resultConsumer(
237 {
238 makeQOhosOptional(
239 isQOhosUdmfDataConvertedFromThisProcessMimeData(*optPasteboardUdmfData)
240 ? PasteboardDataSource::OurProcess
241 : PasteboardDataSource::OtherProcess),
242 makeLazyFetchingQMimeDataFactoryFromUdmfData(std::move(*optPasteboardUdmfData))
243 });
244 });
245 });
246
247 return PasteboardData{
248 .dataSource = dataSource,
249 .lazyFetchingData = mimeDataFactory(),
250 };
251}
252
254 std::shared_ptr<QMimeData> mimeData, const QOhosOptional<bool> &shareInAppOnly)
255{
256 if (!mimeData)
257 return;
258
259 auto udmfDataFactory = makeLazyProcessingUdmfDataFactoryFromQMimeData(mimeData, shareInAppOnly);
260
262 [&](QtOhos::JsState &) {
263 auto udmfData = udmfDataFactory();
264
265 int res = QArkUi::callArkUi(
266 Q_OHOS_NAMED_FUNC(::OH_Pasteboard_SetData),
267 m_pasteboard.get(), udmfData.nativePtr());
268 if (res != ::PASTEBOARD_ErrCode::ERR_OK) {
269 qOhosPrintfError("%s: cannot set data for pasteboard.", Q_FUNC_INFO);
270 return;
271 }
272 });
273}
274
275QT_END_NAMESPACE
void setMimeDataSync(std::shared_ptr< QMimeData > mimeData, const QOhosOptional< bool > &shareInAppOnly)
QOhosClipboardObject(std::function< void(QOhosOptional< PasteboardDataSource >)> &&pasteboardUpdatesNotifier)
PasteboardData getPasteboardDataWithLazyFetch()
std::enable_if_t< qohosplugincore_h_detail::isQOhosOptional< QOhosInvokeResult< Func, T > >, QOhosInvokeResult< Func, T > > andThen(Func &&func) const
Combined button and popup list for selecting options.
std::shared_ptr<::OH_PasteboardObserver > createPasteboardDataObserver()
std::shared_ptr< void > subscribePasteboardObserver(std::shared_ptr<::OH_Pasteboard > pasteboard, std::shared_ptr<::OH_PasteboardObserver > pasteboardObserver, ::Pasteboard_NotifyType notifyType, std::function< void()> dataChangedFunc)
const char * getPasteboardDataSourceAsString(QOhosClipboardObject::PasteboardDataSource dataSource)
std::shared_ptr< void > addPasteboardDataChangedListener(std::shared_ptr<::OH_Pasteboard > pasteboard, std::function< void()> dataChangedListener, std::vector<::Pasteboard_NotifyType > monitoredNotifyTypes)
const char * getPasteboardNotifyTypeAsString(::Pasteboard_NotifyType notifyType)
std::unique_ptr< QOhosUdmfData > tryGetUdmfDataFromPasteboard(::OH_Pasteboard *pasteboard)
void runInJsThreadAndWait(const std::function< void(JsState &)> &task)
QOhosOptional< void > makeEmptyQOhosOptional()
std::weak_ptr< QOhosClipboardObject > weakThis