175 QtOhos::QThreadSafeRef<Context> contextRef,
176 QOhosSupplier<ch::nanoseconds> timeoutsSupplier)
178 auto batchUpdater = makeQtOhosBatchingMTRequestsHandler<std::function<
void(Context &)>>(
179 [contextRef](std::function<
void()> task) {
180 contextRef.visitInQtThreadIfAlive([task = std::move(task)](Context &) {
184 [contextRef](std::function<
void(Context &)> &&request) {
185 request(*contextRef.data());
188 struct ExecutorContext {
189 decltype(batchUpdater) batchUpdater;
190 QOhosSupplier<ch::nanoseconds> timeoutsSupplier;
193 auto executorContext = QtOhos::moveToSharedPtr(
195 .batchUpdater = std::move(batchUpdater),
196 .timeoutsSupplier = std::move(timeoutsSupplier),
199 return [executorContext](std::function<Result(Context &)> qtThreadProcessFunc) {
200 const auto maxResultWaitTime = executorContext->timeoutsSupplier();
202 auto promise = std::make_shared<std::promise<Result>>();
203 auto future = promise->get_future();
205 executorContext->batchUpdater(
206 [&](std::function<
void(Context &)> &request) {
207 request = [qtThreadProcessFunc = std::move(qtThreadProcessFunc), promise](Context &context) {
208 promise->set_value(qtThreadProcessFunc(context));
212 return future.wait_for(maxResultWaitTime) == std::future_status::ready
213 ? std::optional<Result>(future.get())
247 QOhosSupplier<std::unique_ptr<QMimeData>> dropDataFactory,
std::int32_t pendingDropRequestId)
249 qOhosPrintfDebug(
"%s: async processing of drop request with id=%d", Q_FUNC_INFO, pendingDropRequestId);
251 auto qtDropActionConsumer = moveToSharedPtr(
252 QtOhos::makeCallOnceConsumerWrapper<QtOhos::JsState &, Qt::DropAction>(
253 [pendingDropRequestId](QtOhos::JsState &, Qt::DropAction qtDropAction) {
255 "%s: got qtDropAction=%d for drop request with id=%d",
256 Q_FUNC_INFO,
static_cast<
int>(qtDropAction), pendingDropRequestId);
257 QArkUi::callArkUiOrFailOnErrorResult(
258 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NotifyDragResult),
259 pendingDropRequestId,
260 qtDropAction != Qt::IgnoreAction
261 ? ::ARKUI_DRAG_RESULT_SUCCESSFUL
262 : ::ARKUI_DRAG_RESULT_FAILED);
263 QArkUi::callArkUiOrFailOnErrorResult(
264 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NotifyDragEndPendingDone),
265 pendingDropRequestId);
268 constexpr auto notifyDragEndPendingTimeout = ch::milliseconds(1500);
269 QtOhos::setJsTimeout(
271 [pendingDropRequestId, qtDropActionConsumer](
const QtOhos::CallbackInfo &cbInfo) {
272 if ((*qtDropActionConsumer)(cbInfo.jsState(), Qt::IgnoreAction))
273 qOhosPrintfDebug(
"%s: used timeout action for drop request with id=%d", Q_FUNC_INFO, pendingDropRequestId);
275 notifyDragEndPendingTimeout);
277 qWindowRef.visitInQtThreadIfAlive(
278 [dragEventInfo, dropDataFactory = std::move(dropDataFactory), qtDropActionConsumer](QWindow &qWindow)
mutable {
279 auto dropAction = processDropInQWindow(qWindow, dragEventInfo, std::move(dropDataFactory));
282 (*qtDropActionConsumer)(jsState, dropAction);
345 QtOhos::QThreadSafeRef<QWindow> qWindowRef)
347 auto qtThreadMoveEventsProcessor = makeBestEffortQtThreadFunctionsExecutor<QWindow, Qt::DropAction>(
348 qWindowRef, makeDragMoveQtThreadWaitTimeoutsSupplier());
349 auto eventsHandler = [qWindowRef, qtThreadMoveEventsProcessor = std::move(qtThreadMoveEventsProcessor)](
350 QtOhos::JsState &jsState, ::ArkUI_NodeEvent *nodeEvent) {
351 auto eventType = QArkUi::callArkUi(Q_OHOS_NAMED_FUNC(OH_ArkUI_NodeEvent_GetEventType), nodeEvent);
352 auto *dragEvent = QArkUi::callArkUiOrFailOnNullResult(Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeEvent_GetDragEvent), nodeEvent);
353 auto node = QArkUi::callArkUiOrFailOnNullResult(Q_OHOS_NAMED_FUNC(OH_ArkUI_NodeEvent_GetNodeHandle), nodeEvent);
355 auto touchDisplayPosition = getDragEventTouchDisplayPosition(dragEvent);
356 auto nodeDisplayPosition = QArkUi::Node::nodeDisplayPosition(node);
357 auto localPosition = touchDisplayPosition - nodeDisplayPosition;
359 DragEventInfo dragEventInfo = {
360 .localDropPos = localPosition,
361 .dropActions = mapQOhosArkUiDropOperationToQt(getQOhosDragEventDropOperation(dragEvent)),
362 .keyboardModifiers = mapArkUiModifierKeyStatesToQt(getDragEventModifierKeyStates(dragEvent)),
365 qOhosPrintfDebug(
"QNativeNode: got drag event: %d, (%d,%d)", eventType, dragEventInfo.localDropPos.x(), dragEventInfo.localDropPos.y());
368 case ::NODE_ON_DRAG_ENTER:
369 case ::NODE_ON_DRAG_MOVE:
371 auto dropDataFactory = makeDummyQMimeDataFactoryFromUdmfDataTypes(
372 getDragEventDataTypes(dragEvent));
373 auto qtDropAction = qtThreadMoveEventsProcessor(
374 [dragEventInfo, dropDataFactory = std::move(dropDataFactory)](QWindow &qWindow) {
375 QDrag *currentDrag = QDragManager::self()->object();
376 QPlatformDragQtResponse qtResponse = QWindowSystemInterface::handleDrag(
378 currentDrag !=
nullptr ? currentDrag->mimeData() : dropDataFactory().get(),
379 dragEventInfo.localDropPos,
380 currentDrag !=
nullptr ? currentDrag->supportedActions() : dragEventInfo.dropActions,
381 Qt::LeftButton, dragEventInfo.keyboardModifiers);
382 if (currentDrag !=
nullptr && qtResponse.isAccepted() && qtResponse.acceptedAction() != Qt::IgnoreAction)
383 getQOhosPlatformDrag()->updateDropAction(qtResponse.acceptedAction());
384 return qtResponse.acceptedAction();
386 QArkUi::callArkUiOrFailOnErrorResult(
387 Q_OHOS_NAMED_FUNC(::OH_ArkUI_DragEvent_SetDragResult),
389 qtDropAction.value_or(Qt::IgnoreAction) != Qt::IgnoreAction
392 setDragEventSuggestedDropOperationIfAvailable(
393 dragEvent, qAndThen(qtDropAction, &tryMapQOhosArkUiDropOperationFromQt));
396 case ::NODE_ON_DRAG_LEAVE:
397 qWindowRef.visitInQtThreadIfAlive(
398 [](QWindow &qWindow) {
399 std::ignore = QWindowSystemInterface::handleDrag(
400 &qWindow,
nullptr, QPoint(), Qt::IgnoreAction, Qt::MouseButtons(), Qt::KeyboardModifiers());
405 QOhosSupplier<std::unique_ptr<QMimeData>> dropDataFactory;
406 if (getDragEventDataTypeCount(dragEvent) != 0) {
407 auto optDragUdmfData = tryGetDragEventUdmfDataOrNull(dragEvent);
408 dropDataFactory = optDragUdmfData
409 ? createQMimeDataFactoryFromUdmfData(std::move(*optDragUdmfData))
410 : &std::make_unique<QMimeData>;
412 dropDataFactory = &std::make_unique<QMimeData>;
414 auto copyableDropDataFactory = makeImplicitlySharedSupplier(std::move(dropDataFactory));
416 bool asyncProcessingStarted = tryStartAsyncProcessingOfDropEvent(
417 jsState, dragEvent, qWindowRef, dragEventInfo, copyableDropDataFactory);
419 if (!asyncProcessingStarted) {
420 auto qtDropAction = tryRunInQtThreadAndGetResult<QWindow, Qt::DropAction>(
422 [dragEventInfo, copyableDropDataFactory](QWindow &qWindow) {
423 return processDropInQWindow(qWindow, dragEventInfo, copyableDropDataFactory);
425 QArkUi::callArkUiOrFailOnErrorResult(
426 Q_OHOS_NAMED_FUNC(::OH_ArkUI_DragEvent_SetDragResult),
428 qtDropAction.value_or(Qt::IgnoreAction) != Qt::IgnoreAction
429 ? ::ARKUI_DRAG_RESULT_SUCCESSFUL
430 : ::ARKUI_DRAG_RESULT_FAILED);
431 setDragEventSuggestedDropOperationIfAvailable(
432 dragEvent, qAndThen(qtDropAction, &tryMapQOhosArkUiDropOperationFromQt));
441 return [eventsHandler = std::move(eventsHandler)](::ArkUI_NodeEvent *nodeEvent) {
442 QtOhos::runInJsThreadAndWait(
443 [&](QtOhos::JsState &jsState) {
444 eventsHandler(jsState, nodeEvent);