174 QtOhos::QThreadSafeRef<Context> contextRef,
175 QOhosSupplier<ch::nanoseconds> timeoutsSupplier)
177 auto batchUpdater = makeQtOhosBatchingMTRequestsHandler<std::function<
void(Context &)>>(
178 [contextRef](std::function<
void()> task) {
179 contextRef.visitInQtThreadIfAlive([task = std::move(task)](Context &) {
183 [contextRef](std::function<
void(Context &)> &&request) {
184 request(*contextRef.data());
187 struct ExecutorContext {
188 decltype(batchUpdater) batchUpdater;
189 QOhosSupplier<ch::nanoseconds> timeoutsSupplier;
192 auto executorContext = QtOhos::moveToSharedPtr(
194 .batchUpdater = std::move(batchUpdater),
195 .timeoutsSupplier = std::move(timeoutsSupplier),
198 return [executorContext](std::function<Result(Context &)> qtThreadProcessFunc) {
199 const auto maxResultWaitTime = executorContext->timeoutsSupplier();
201 auto promise = std::make_shared<std::promise<Result>>();
202 auto future = promise->get_future();
204 executorContext->batchUpdater(
205 [&](std::function<
void(Context &)> &request) {
206 request = [qtThreadProcessFunc = std::move(qtThreadProcessFunc), promise](Context &context) {
207 promise->set_value(qtThreadProcessFunc(context));
211 return future.wait_for(maxResultWaitTime) == std::future_status::ready
212 ? makeQOhosOptional(future.get())
213 : makeEmptyQOhosOptional();
246 QOhosSupplier<std::unique_ptr<QMimeData>> dropDataFactory,
std::int32_t pendingDropRequestId)
248 qOhosPrintfDebug(
"%s: async processing of drop request with id=%d", Q_FUNC_INFO, pendingDropRequestId);
250 auto qtDropActionConsumer = moveToSharedPtr(
251 QtOhos::makeCallOnceConsumerWrapper<QtOhos::JsState &, Qt::DropAction>(
252 [pendingDropRequestId](QtOhos::JsState &, Qt::DropAction qtDropAction) {
254 "%s: got qtDropAction=%d for drop request with id=%d",
255 Q_FUNC_INFO,
static_cast<
int>(qtDropAction), pendingDropRequestId);
256 QArkUi::callArkUiOrFailOnErrorResult(
257 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NotifyDragResult),
258 pendingDropRequestId,
259 qtDropAction != Qt::IgnoreAction
260 ? ::ARKUI_DRAG_RESULT_SUCCESSFUL
261 : ::ARKUI_DRAG_RESULT_FAILED);
262 QArkUi::callArkUiOrFailOnErrorResult(
263 Q_OHOS_NAMED_FUNC(::OH_ArkUI_NotifyDragEndPendingDone),
264 pendingDropRequestId);
267 constexpr auto notifyDragEndPendingTimeout = ch::milliseconds(1500);
268 QtOhos::setJsTimeout(
270 [pendingDropRequestId, qtDropActionConsumer](
const QtOhos::CallbackInfo &cbInfo) {
271 if ((*qtDropActionConsumer)(cbInfo.jsState(), Qt::IgnoreAction))
272 qOhosPrintfDebug(
"%s: used timeout action for drop request with id=%d", Q_FUNC_INFO, pendingDropRequestId);
274 notifyDragEndPendingTimeout);
276 qWindowRef.visitInQtThreadIfAlive(
277 [dragEventInfo, dropDataFactory = std::move(dropDataFactory), qtDropActionConsumer](QWindow &qWindow)
mutable {
278 auto dropAction = processDropInQWindow(qWindow, dragEventInfo, std::move(dropDataFactory));
281 (*qtDropActionConsumer)(jsState, dropAction);
344 QtOhos::QThreadSafeRef<QWindow> qWindowRef)
346 auto qtThreadMoveEventsProcessor = makeBestEffortQtThreadFunctionsExecutor<QWindow, Qt::DropAction>(
347 qWindowRef, makeDragMoveQtThreadWaitTimeoutsSupplier());
348 auto eventsHandler = [qWindowRef, qtThreadMoveEventsProcessor = std::move(qtThreadMoveEventsProcessor)](
349 QtOhos::JsState &jsState, ::ArkUI_NodeEvent *nodeEvent) {
350 auto eventType = QArkUi::callArkUi(Q_OHOS_NAMED_FUNC(OH_ArkUI_NodeEvent_GetEventType), nodeEvent);
351 auto *dragEvent = QArkUi::callArkUiOrFailOnNullResult(Q_OHOS_NAMED_FUNC(::OH_ArkUI_NodeEvent_GetDragEvent), nodeEvent);
352 auto node = QArkUi::callArkUiOrFailOnNullResult(Q_OHOS_NAMED_FUNC(OH_ArkUI_NodeEvent_GetNodeHandle), nodeEvent);
354 auto touchDisplayPosition = getDragEventTouchDisplayPosition(dragEvent);
355 auto nodeDisplayPosition = QArkUi::Node::nodeDisplayPosition(node);
356 auto localPosition = touchDisplayPosition - nodeDisplayPosition;
358 DragEventInfo dragEventInfo = {
359 .localDropPos = localPosition,
360 .dropActions = mapQOhosArkUiDropOperationToQt(getQOhosDragEventDropOperation(dragEvent)),
361 .keyboardModifiers = mapArkUiModifierKeyStatesToQt(getDragEventModifierKeyStates(dragEvent)),
364 qOhosPrintfDebug(
"QNativeNode: got drag event: %d, (%d,%d)", eventType, dragEventInfo.localDropPos.x(), dragEventInfo.localDropPos.y());
367 case ::NODE_ON_DRAG_ENTER:
368 case ::NODE_ON_DRAG_MOVE:
370 auto dropDataFactory = makeDummyQMimeDataFactoryFromUdmfDataTypes(
371 getDragEventDataTypes(dragEvent));
372 auto qtDropAction = qtThreadMoveEventsProcessor(
373 [dragEventInfo, dropDataFactory = std::move(dropDataFactory)](QWindow &qWindow) {
374 QDrag *currentDrag = QDragManager::self()->object();
375 QPlatformDragQtResponse qtResponse = QWindowSystemInterface::handleDrag(
377 currentDrag !=
nullptr ? currentDrag->mimeData() : dropDataFactory().get(),
378 dragEventInfo.localDropPos,
379 currentDrag !=
nullptr ? currentDrag->supportedActions() : dragEventInfo.dropActions,
380 Qt::LeftButton, dragEventInfo.keyboardModifiers);
381 if (currentDrag !=
nullptr && qtResponse.isAccepted() && qtResponse.acceptedAction() != Qt::IgnoreAction)
382 getQOhosPlatformDrag()->updateDropAction(qtResponse.acceptedAction());
383 return qtResponse.acceptedAction();
385 QArkUi::callArkUiOrFailOnErrorResult(
386 Q_OHOS_NAMED_FUNC(::OH_ArkUI_DragEvent_SetDragResult),
388 qtDropAction.value_or(Qt::IgnoreAction) != Qt::IgnoreAction
391 setDragEventSuggestedDropOperationIfAvailable(
392 dragEvent, qAndThen(qtDropAction, &tryMapQOhosArkUiDropOperationFromQt));
395 case ::NODE_ON_DRAG_LEAVE:
396 qWindowRef.visitInQtThreadIfAlive(
397 [](QWindow &qWindow) {
398 std::ignore = QWindowSystemInterface::handleDrag(
399 &qWindow,
nullptr, QPoint(), Qt::IgnoreAction, Qt::MouseButtons(), Qt::KeyboardModifiers());
404 QOhosSupplier<std::unique_ptr<QMimeData>> dropDataFactory;
405 if (getDragEventDataTypeCount(dragEvent) != 0) {
406 auto optDragUdmfData = tryGetDragEventUdmfDataOrNull(dragEvent);
407 dropDataFactory = optDragUdmfData
408 ? createQMimeDataFactoryFromUdmfData(std::move(*optDragUdmfData))
409 : &std::make_unique<QMimeData>;
411 dropDataFactory = &std::make_unique<QMimeData>;
413 auto copyableDropDataFactory = makeImplicitlySharedSupplier(std::move(dropDataFactory));
415 bool asyncProcessingStarted = tryStartAsyncProcessingOfDropEvent(
416 jsState, dragEvent, qWindowRef, dragEventInfo, copyableDropDataFactory);
418 if (!asyncProcessingStarted) {
419 auto qtDropAction = tryRunInQtThreadAndGetResult<QWindow, Qt::DropAction>(
421 [dragEventInfo, copyableDropDataFactory](QWindow &qWindow) {
422 return processDropInQWindow(qWindow, dragEventInfo, copyableDropDataFactory);
424 QArkUi::callArkUiOrFailOnErrorResult(
425 Q_OHOS_NAMED_FUNC(::OH_ArkUI_DragEvent_SetDragResult),
427 qtDropAction.value_or(Qt::IgnoreAction) != Qt::IgnoreAction
428 ? ::ARKUI_DRAG_RESULT_SUCCESSFUL
429 : ::ARKUI_DRAG_RESULT_FAILED);
430 setDragEventSuggestedDropOperationIfAvailable(
431 dragEvent, qAndThen(qtDropAction, &tryMapQOhosArkUiDropOperationFromQt));
440 return [eventsHandler = std::move(eventsHandler)](::ArkUI_NodeEvent *nodeEvent) {
441 QtOhos::runInJsThreadAndWait(
442 [&](QtOhos::JsState &jsState) {
443 eventsHandler(jsState, nodeEvent);