4#include <qohosfloatingwindow.h>
6#include <QtCore/private/qohoslogger_p.h>
7#include "QtGui/private/qguiapplication_p.h"
8#include <QtGui/private/qwindow_p.h>
9#include <qohosdeviceinfo_p.h>
10#include <qohosinputcontext.h>
11#include <qohosinputmethodeventhandler.h>
12#include <qohosjsmain.h>
13#include <qohosplatformbackingstore.h>
14#include <qohosplatformwindow.h>
15#include <qohosruntimedevicetypeandmode.h>
16#include <qohossettings.h>
17#include <render/qohossurface.h>
18#include <render/qohoswindowproxy.h>
19#include <render/qwindowproxyregistry.h>
29 && rectChangeOptions.rect.isValid()
30 && window->geometry() != rectChangeOptions.rect
36 return QGuiApplicationPrivate::focus_window == windowLosingSystemFocus
37 || (QGuiApplicationPrivate::focus_window !=
nullptr
38 && QOhosPlatformWindow::platformWindowFlagsForQWindow(
39 QGuiApplicationPrivate::focus_window).testFlag(Qt::WindowDoesNotAcceptFocus));
59 bool geometryControlledBySystem =
62 && view->viewType() == QOhosView::ViewType::MainWindow;
64 if (geometryControlledBySystem) {
65 const auto actualGeometry = QPlatformWindow::geometry();
66 QPlatformWindow::setGeometry(rect);
67 setWindowGeometryFromOhos(actualGeometry);
71 auto *currentScreen = QOhosPlatformWindow::screen();
72 QOhosPlatformWindow::setGeometry(rect);
73 const auto frameGeometry = lastRequestedWindowFrameGeometry();
75 auto *targetScreen = QOhosPlatformWindow::screenForGeometry(frameGeometry);
76 if (targetScreen !=
nullptr && targetScreen != currentScreen)
77 QWindowSystemInterface::handleWindowScreenChanged(window(), targetScreen->screen());
79 if (view !=
nullptr) {
80 if (!qt_window_private(window())->positionAutomatic)
81 view->setPosition(frameGeometry.topLeft());
82 view->setSize(frameGeometry.size());
84 if (view->viewType() == QOhosView::ViewType::EmbeddedWindow)
85 setWindowGeometryFromOhos(rect);
86 else if (rect.size() != lastReportedWindowSize())
87 m_optSizeBeforeResizeRequest = lastReportedWindowSize();
89 m_optSizeBeforeResizeRequest.reset();
98 m_view->showImmediate();
99 startAsyncWaitForNodeResizeIfNeeded();
104 auto windowObjectName = window()->objectName();
107 "%s: winId called for window named: \"%s\"",
109 windowObjectName.toStdString().c_str());
111 return reinterpret_cast<WId>(m_view->viewWindowId());
117 if (view !=
nullptr) {
119 window()->requestUpdate();
126 if (view !=
nullptr) {
128 window()->requestUpdate();
146 m_view = QOhosView::createForWindow(
this, propertiesProvider());
148 auto *qWindow = window();
154 if (m_view->viewType() == QOhosView::ViewType::MainWindow
155 && !QOhosSettings::instance().isWindowPcModeEnabled()
156 && !m_lastWindowStatusType.has_value()) {
157 m_lastWindowStatusType = QOhosWindowProxy::WindowStatusType::FULL_SCREEN;
161 m_view.get(), &QOhosView::externalContentInteractionDetected,
162 qWindow, &QOhosPlatformWindow::closeAllActivePopups);
165 m_view.get(), &QOhosView::nodeAreaChanged, m_view.get(),
166 [
this](QArkUi::QQtEmbeddedWindowNode::NodeAreaInfo event) {
167 handleNodeResizeEvent(event);
171 m_view.get(), &QOhosView::windowEvent,
173 [
this](QOhosWindowProxy::WindowEvent evt) { handleWindowEvent(evt); });
176 m_view.get(), &QOhosView::windowStatusChange,
178 [
this](QOhosWindowProxy::WindowStatus evt) { handleWindowStatusChange(evt); });
181 m_view.get(), &QOhosView::windowVisibilityChange,
183 [
this](
bool visible) { handleWindowVisibilityChange(visible); });
185 bool monitorAvoidAreaChange =
186 !(isHandheldDeviceType() && m_view->viewType() == QOhosView::ViewType::SubWindow);
188 if (monitorAvoidAreaChange) {
190 m_view.get(), &QOhosView::avoidAreaChanged,
192 [
this](QOhosWindowProxy::AvoidAreaType avoidAreaType,
193 const QOhosWindowProxy::AvoidArea &systemAvoidArea) {
194 handleAvoidAreaChanged(avoidAreaType, systemAvoidArea);
199 m_view.get(), &QOhosView::windowRectChangedInGlobalDisplay,
201 [
this](
const QOhosWindowProxy::RectChangeOptions &rectChangeOptions) {
202 handleWindowRectChanged(rectChangeOptions);
205 QObject::connect(qWindow, &QWindow::modalityChanged, m_view.get(), &QOhosView::setModality);
208 m_view.get(), &QOhosView::surfaceStatusChanged,
210 [
this](
const std::optional<QSize> &optSurfaceSize) { handleSurfaceStatusChanged(optSurfaceSize); });
212 QObject::connect(qWindow, &QWindow::windowTitleChanged, m_view.get(), &QOhosView::setTitle);
215 m_view.get(), &QOhosView::windowDisplayIdChanged,
217 [
this](QOhosDisplayInfo::JsDisplayId displayId) { handleWindowDisplayIdChanged(displayId); });
223 if (view !=
nullptr && m_cursor.has_value())
224 view->setCursor(m_cursor.value());
228 Qt::WindowFlags previousWindowFlags, Qt::WindowFlags currentWindowFlags)
234 view->handleWindowFlagsChange(previousWindowFlags, currentWindowFlags);
238 Qt::WindowStates oldWindowState, Qt::WindowStates currentWindowState)
244 view->handleWindowStateChange(oldWindowState, currentWindowState);
249 QWindowSystemInterface::handleFocusWindowChanged(window(), Qt::PopupFocusReason);
255 QWindowSystemInterface::handleFocusWindowChanged(
256 !systemFocusedWindows.empty() ? systemFocusedWindows.front() :
nullptr,
257 Qt::ActiveWindowFocusReason);
262 m_windowMask = region;
281 if (windowFlags().testFlag(Qt::WindowDoesNotAcceptFocus) && window()->type() == Qt::Popup) {
282 internalHijackSystemFocusAsPopup();
291 auto *qWindow = window();
293 auto previousWindowEventType = std::exchange(m_lastWindowEventType, evt.type);
295 if (evt.type != QOhosWindowProxy::WindowEventType::WINDOW_SHOWN)
296 m_activationEventDeferredUntilWindowUnblocked.reset();
299 m_activationEventDeferredUntilExposed.reset();
305 if (m_view->viewType() != QOhosView::ViewType::EmbeddedWindow && !isExposed()) {
306 m_activationEventDeferredUntilExposed = evt;
310 QWindow *modalWindow =
nullptr;
311 if (QGuiApplicationPrivate::instance()->isWindowBlocked(qWindow, &modalWindow)
312 && qWindow != modalWindow) {
313 if (qWindow->isTopLevel())
314 m_activationEventDeferredUntilWindowUnblocked = evt;
315 modalWindow->requestActivate();
323 restoreWindowCurrentCursorIfNeeded();
324 if (windowAcceptsFocusAndInput) {
325 QWindowSystemInterface::handleFocusWindowChanged(qWindow, Qt::ActiveWindowFocusReason);
331 if (!windowAcceptsFocusAndInput)
333 if (shouldClearQtFocusOnSystemFocusLoss(qWindow) && !anyQtWindowHoldsSystemFocus())
334 QWindowSystemInterface::handleFocusWindowChanged(
nullptr, Qt::ActiveWindowFocusReason);
338 if (!checkWindowAcceptsFocus() && QGuiApplicationPrivate::focus_window == qWindow)
339 focusHijackingPopupHidden();
340 updateMinimizedFromPlatformVisibility(
false);
341 setShownFromOhos(
false);
351 qWindow->setVisible(
true);
352 updateMinimizedFromPlatformVisibility(
true);
353 setShownFromOhos(
true);
354 startAsyncWaitForNodeResizeIfNeeded();
364 if (m_view->viewType() != QOhosView::ViewType::SubWindow)
367 const bool platformHidden = !platformShown;
368 if (platformHidden && !window()->isVisible())
371 auto states = windowStates();
372 if (states.testFlag(Qt::WindowMinimized) == platformHidden)
375 states.setFlag(Qt::WindowMinimized, platformHidden);
376 setWindowStateFromOhos(states);
381 auto *qWindow = window();
384 "Window status changed, window: %p(%s) status: %d",
386 qPrintable(qWindow->objectName()),
391 if (m_lastWindowStatusType == evt.type
392 && m_lastWindowStatusType == QOhosWindowProxy::WindowStatusType::FULL_SCREEN
393 && !(m_view->viewType() == QOhosView::ViewType::MainWindow
394 && !QOhosSettings::instance().isWindowPcModeEnabled())) {
395 qCDebug(QtForOhos,
"Window status is the same as the previous one");
399 Qt::WindowStates windowStatesToSet = windowStates();
400 m_lastWindowStatusType = evt.type;
407 windowStatesToSet = m_view->isFullscreenImmersiveModeEnabled()
408 ? Qt::WindowState::WindowFullScreen
409 : Qt::WindowState::WindowMaximized;
412 if (m_view->consumePendingSelfMinimizeEcho()) {
422 windowStatesToSet.setFlag(Qt::WindowState::WindowMinimized);
427 windowStatesToSet = Qt::WindowState::WindowNoState;
431 setWindowStateFromOhos(windowStatesToSet);
437 startAsyncWaitForNodeResizeIfNeeded();
442 auto *qWindow = window();
445 "Window %p(%s) visibility changed: %s",
447 qPrintable(qWindow->objectName()),
448 visible ?
"true" :
"false");
449 if (visible && m_windowMask.has_value())
450 m_view->setWindowMask(QOhosWindowProxy::WindowMask{m_windowMask.value()});
452 setShownFromOhos(visible);
457 m_shownFromOhos = shown;
459 activateIfDeferredUntilExposed();
467 if (
auto deferredActivationEvent = std::exchange(m_activationEventDeferredUntilExposed, std::nullopt))
468 handleWindowEvent(*deferredActivationEvent);
473 const QOhosWindowProxy::AvoidArea &systemAvoidArea)
475 const auto &cached = m_avoidAreaCache[avoidAreaType];
477 bool actuallyChanged =
478 cached.visible != systemAvoidArea.visible
479 || cached.leftRect != systemAvoidArea.leftRect
480 || cached.rightRect != systemAvoidArea.rightRect
481 || cached.bottomRect != systemAvoidArea.bottomRect
482 || cached.topRect != systemAvoidArea.topRect;
484 if (actuallyChanged) {
485 m_avoidAreaCache[avoidAreaType] = systemAvoidArea;
486 qCDebug(QtForOhos) <<
"Avoid area changed:"
487 <<
static_cast<
int>(avoidAreaType)
488 <<
"visible:" << systemAvoidArea.visible
489 <<
"top:" << systemAvoidArea.topRect
490 <<
"left:" << systemAvoidArea.leftRect
491 <<
"right:" << systemAvoidArea.rightRect
492 <<
"bottom:" << systemAvoidArea.bottomRect;
493 startAsyncWaitForNodeResizeIfNeeded();
497void QOhosFloatingWindow::handleSurfaceStatusChanged(
const std::optional<QSize> &optSurfaceSize)
499 m_optLastSurfaceSize = optSurfaceSize;
500 bool hasSurface = m_view->surfaceOrNull() !=
nullptr;
501 if (m_view->viewType() == QOhosView::ViewType::EmbeddedWindow) {
503 }
else if (m_shownFromOhos && hasSurface !=
isExposed()) {
505 activateIfDeferredUntilExposed();
509 startAsyncWaitForNodeResizeIfNeeded();
515 startAsyncWaitForNodeResizeIfNeeded();
519 const QOhosWindowProxy::RectChangeOptions &rectChangeOptions)
524 <<
"windowRectChanged window:" << window()
525 <<
"rect:" << rectChangeOptions.rect
526 <<
"reason:" <<
static_cast<
int>(rectChangeOptions.reason);
528 if (rectChangeOptions.rect.size() != lastRequestedWindowFrameGeometry().size())
529 m_optSizeBeforeResizeRequest.reset();
531 startAsyncWaitForNodeResizeIfNeeded();
533 if (isWindowRotatedByTabletScreenRotation(window(), rectChangeOptions))
534 needsCloseAllActivePopups =
true;
536 if (needsCloseAllActivePopups)
542 if (event->type() == QEvent::WindowUnblocked) {
543 auto deferredActivationEvent =
544 std::exchange(m_activationEventDeferredUntilWindowUnblocked, std::nullopt);
545 const QWindow *windowHoldingFocus = QGuiApplicationPrivate::focus_window;
546 bool noVisibleWindowHoldsFocus =
547 windowHoldingFocus ==
nullptr || !windowHoldingFocus->isVisible();
548 if (deferredActivationEvent && noVisibleWindowHoldsFocus)
549 handleWindowEvent(*deferredActivationEvent);
552 if (event->type() == QEvent::Timer) {
553 auto *timerEvent =
static_cast<QTimerEvent *>(event);
554 if (m_view && timerEvent->timerId() == m_geometryChangeTimer.timerId()) {
555 auto syntheticEvent = m_view->nodeAreaInfo();
556 handleNodeResizeEvent(syntheticEvent);
560 return QOhosPlatformWindow::windowEvent(event);
565 constexpr auto geometryChangeEventTimeoutMs = std::chrono::milliseconds(16);
567 if (!m_geometryChangeTimer.isActive()) {
568 m_geometryChangeTimer.start(
569 geometryChangeEventTimeoutMs.count(),
577 m_geometryChangeTimer.stop();
579 if (Q_UNLIKELY(!m_view))
582 if (m_view->viewType() != QOhosView::ViewType::EmbeddedWindow) {
583 const QSize size = areaChangeEvent.screenGeometryPixels.size();
587 if (size != m_optSizeBeforeResizeRequest) {
588 m_optSizeBeforeResizeRequest.reset();
589 setWindowGeometryFromOhos(QRect(areaChangeEvent.globalRelativeOffsetPixels, size));
593 updateSafeAreaMargins();
601 for (
const QRect &cutout : cutoutRects) {
602 if (cutout.isEmpty() || !cutout.intersects(windowRect))
604 const int distTop = cutout.top() - windowRect.top();
605 const int distBottom = windowRect.bottom() - cutout.bottom();
606 const int distLeft = cutout.left() - windowRect.left();
607 const int distRight = windowRect.right() - cutout.right();
608 int nearest = qMin(qMin(distTop, distBottom), qMin(distLeft, distRight));
609 if (nearest == distTop)
610 margins.setTop(qMax(margins.top(), cutout.bottom() + 1 - windowRect.top()));
611 else if (nearest == distBottom)
612 margins.setBottom(qMax(margins.bottom(), windowRect.bottom() + 1 - cutout.top()));
613 else if (nearest == distLeft)
614 margins.setLeft(qMax(margins.left(), cutout.right() + 1 - windowRect.left()));
616 margins.setRight(qMax(margins.right(), windowRect.right() + 1 - cutout.left()));
625 static constexpr QOhosWindowProxy::
AvoidAreaType kSafeAreaContributors[] = {
634 const QRect frame = m_view->viewGeometry().frameGeometry;
635 const QRect content = m_view->nodeScreenGeometryPixels();
636 if (!frame.contains(content))
638 const int alreadyTop = content.top() - frame.top();
639 const int alreadyLeft = content.left() - frame.left();
640 const int alreadyRight = frame.right() - content.right();
641 const int alreadyBottom = frame.bottom() - content.bottom();
644 for (
auto type : kSafeAreaContributors) {
645 const QMargins m = m_view->avoidAreaMargins(type);
646 combined.setTop(qMax(combined.top(), qMax(0, m.top() - alreadyTop)));
647 combined.setLeft(qMax(combined.left(), qMax(0, m.left() - alreadyLeft)));
648 combined.setRight(qMax(combined.right(), qMax(0, m.right() - alreadyRight)));
649 combined.setBottom(qMax(combined.bottom(), qMax(0, m.bottom() - alreadyBottom)));
655 const QMargins cutout = cutoutMarginsForWindow(m_view->displayCutoutRects(), content);
656 combined.setTop(qMax(combined.top(), cutout.top()));
657 combined.setLeft(qMax(combined.left(), cutout.left()));
658 combined.setRight(qMax(combined.right(), cutout.right()));
659 combined.setBottom(qMax(combined.bottom(), cutout.bottom()));
661 setSafeAreaMarginsFromOhos(combined);
QOhosFloatingWindow(QWindow *window)
~QOhosFloatingWindow() override
void requestActivateWindow() override
Reimplement to let Qt be able to request activation/focus for a window.
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
bool startSystemMove() override
Reimplement this method to start a system move operation if the system supports it and return true to...
QOhosView * ownedViewOrNull() const override
void onWindowStateChanged(Qt::WindowStates oldWindowState, Qt::WindowStates currentWindowState) override
WId winId() const override
Reimplement in subclasses to return a handle to the native window.
void initialize() override
Called as part of QWindow::create(), after constructing the window.
void onWindowFlagsChanged(Qt::WindowFlags previousWindowFlags, Qt::WindowFlags currentWindowFlags) override
bool windowEvent(QEvent *event) override
Reimplement this method to be able to do any platform specific event handling.
void setGeometry(const QRect &rect) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
QOhosSurface * ownedSurfaceOrNull() const override
void setMask(const QRegion ®ion) override
Reimplement to be able to let Qt set the mask of a window.
void lower() override
Reimplement to be able to let Qt lower windows to the bottom of the desktop.
void raise() override
Reimplement to be able to let Qt raise windows to the top of the desktop.
bool isWindowPcModeEnabled() const
static QOhosSettings & instance()
QOhosSurface * surfaceOrNull() const
void setWindowMask(const QOhosWindowProxy::WindowMask &windowMask)
QtOhosQpa::enums::ohos::window::WindowEventType WindowEventType
QtOhosQpa::enums::ohos::window::RectChangeReason RectChangeReason
QtOhosQpa::enums::ohos::window::AvoidAreaType AvoidAreaType
QtOhosQpa::enums::ohos::window::WindowStatusType WindowStatusType
static QWindowProxyRegistry & instance()
Combined button and popup list for selecting options.
bool shouldClearQtFocusOnSystemFocusLoss(QWindow *windowLosingSystemFocus)
bool anyQtWindowHoldsSystemFocus()
bool isWindowRotatedByTabletScreenRotation(QWindow *window, QOhosWindowProxy::RectChangeOptions rectChangeOptions)
@ TYPE_NAVIGATION_INDICATOR
static QMargins cutoutMarginsForWindow(const QList< QRect > &cutoutRects, const QRect &windowRect)