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 =
60 !QOhosSettings::instance().isWindowPcModeEnabled()
62 && view->viewType() == QOhosView::ViewType::MainWindow;
64 if (geometryControlledBySystem) {
65 setWindowGeometryFromOhos(windowGeometry());
69 auto *currentScreen = QOhosPlatformWindow::screen();
70 QOhosPlatformWindow::setGeometry(rect);
71 const auto frameGeometry = lastRequestedWindowFrameGeometry();
73 auto *targetScreen = QOhosPlatformWindow::screenForGeometry(frameGeometry);
74 if (targetScreen !=
nullptr && targetScreen != currentScreen)
75 QWindowSystemInterface::handleWindowScreenChanged(window(), targetScreen->screen());
77 if (view !=
nullptr) {
78 if (!qt_window_private(window())->positionAutomatic)
79 view->setPosition(frameGeometry.topLeft());
80 view->setSize(frameGeometry.size());
82 if (view->viewType() == QOhosView::ViewType::EmbeddedWindow)
83 setWindowGeometryFromOhos(rect);
84 else if (rect.size() != lastReportedWindowSize())
85 m_optSizeBeforeResizeRequest = lastReportedWindowSize();
87 m_optSizeBeforeResizeRequest.reset();
96 m_view->showImmediate();
97 startAsyncWaitForNodeResizeIfNeeded();
102 auto windowObjectName = window()->objectName();
105 "%s: winId called for window named: \"%s\"",
107 windowObjectName.toStdString().c_str());
109 return reinterpret_cast<WId>(m_view->viewWindowId());
115 if (view !=
nullptr) {
117 window()->requestUpdate();
124 if (view !=
nullptr) {
126 window()->requestUpdate();
144 m_view = QOhosView::createForWindow(
this, propertiesProvider());
146 auto *qWindow = window();
152 if (m_view->viewType() == QOhosView::ViewType::MainWindow
153 && !QOhosSettings::instance().isWindowPcModeEnabled()
154 && !m_lastWindowStatusType.has_value()) {
155 m_lastWindowStatusType = QOhosWindowProxy::WindowStatusType::FULL_SCREEN;
159 m_view.get(), &QOhosView::externalContentInteractionDetected,
160 qWindow, &QOhosPlatformWindow::closeAllActivePopups);
163 m_view.get(), &QOhosView::nodeAreaChanged, m_view.get(),
164 [
this](QArkUi::QQtEmbeddedWindowNode::NodeAreaInfo event) {
165 handleNodeResizeEvent(event);
169 m_view.get(), &QOhosView::windowEvent,
171 [
this](QOhosWindowProxy::WindowEvent evt) { handleWindowEvent(evt); });
174 m_view.get(), &QOhosView::windowStatusChange,
176 [
this](QOhosWindowProxy::WindowStatus evt) { handleWindowStatusChange(evt); });
179 m_view.get(), &QOhosView::windowVisibilityChange,
181 [
this](
bool visible) { handleWindowVisibilityChange(visible); });
183 bool monitorAvoidAreaChange =
184 !(isHandheldDeviceType() && m_view->viewType() == QOhosView::ViewType::SubWindow);
186 if (monitorAvoidAreaChange) {
188 m_view.get(), &QOhosView::avoidAreaChanged,
190 [
this](QOhosWindowProxy::AvoidAreaType avoidAreaType,
191 const QOhosWindowProxy::AvoidArea &systemAvoidArea) {
192 handleAvoidAreaChanged(avoidAreaType, systemAvoidArea);
197 m_view.get(), &QOhosView::windowRectChangedInGlobalDisplay,
199 [
this](
const QOhosWindowProxy::RectChangeOptions &rectChangeOptions) {
200 handleWindowRectChanged(rectChangeOptions);
203 QObject::connect(qWindow, &QWindow::modalityChanged, m_view.get(), &QOhosView::setModality);
206 m_view.get(), &QOhosView::surfaceStatusChanged,
208 [
this](
const std::optional<QSize> &optSurfaceSize) { handleSurfaceStatusChanged(optSurfaceSize); });
210 QObject::connect(qWindow, &QWindow::windowTitleChanged, m_view.get(), &QOhosView::setTitle);
213 m_view.get(), &QOhosView::windowDisplayIdChanged,
215 [
this](QOhosDisplayInfo::JsDisplayId displayId) { handleWindowDisplayIdChanged(displayId); });
221 if (view !=
nullptr && m_cursor.has_value())
222 view->setCursor(m_cursor.value());
226 Qt::WindowFlags previousWindowFlags, Qt::WindowFlags currentWindowFlags)
232 view->handleWindowFlagsChange(previousWindowFlags, currentWindowFlags);
236 Qt::WindowStates oldWindowState, Qt::WindowStates currentWindowState)
242 view->handleWindowStateChange(oldWindowState, currentWindowState);
247 QWindowSystemInterface::handleFocusWindowChanged(window(), Qt::PopupFocusReason);
253 QWindowSystemInterface::handleFocusWindowChanged(
254 !systemFocusedWindows.empty() ? systemFocusedWindows.front() :
nullptr,
255 Qt::ActiveWindowFocusReason);
260 m_windowMask = region;
279 if (windowFlags().testFlag(Qt::WindowDoesNotAcceptFocus) && window()->type() == Qt::Popup) {
280 internalHijackSystemFocusAsPopup();
289 auto *qWindow = window();
291 auto previousWindowEventType = std::exchange(m_lastWindowEventType, evt.type);
293 if (evt.type != QOhosWindowProxy::WindowEventType::WINDOW_SHOWN)
294 m_activationEventDeferredUntilWindowUnblocked.reset();
297 m_activationEventDeferredUntilExposed.reset();
303 if (m_view->viewType() != QOhosView::ViewType::EmbeddedWindow && !isExposed()) {
304 m_activationEventDeferredUntilExposed = evt;
308 QWindow *modalWindow =
nullptr;
309 if (QGuiApplicationPrivate::instance()->isWindowBlocked(qWindow, &modalWindow)
310 && qWindow != modalWindow) {
311 if (qWindow->isTopLevel())
312 m_activationEventDeferredUntilWindowUnblocked = evt;
313 modalWindow->requestActivate();
321 restoreWindowCurrentCursorIfNeeded();
322 if (windowAcceptsFocusAndInput) {
323 QWindowSystemInterface::handleFocusWindowChanged(qWindow, Qt::ActiveWindowFocusReason);
329 if (!windowAcceptsFocusAndInput)
331 if (shouldClearQtFocusOnSystemFocusLoss(qWindow) && !anyQtWindowHoldsSystemFocus())
332 QWindowSystemInterface::handleFocusWindowChanged(
nullptr, Qt::ActiveWindowFocusReason);
336 if (!checkWindowAcceptsFocus() && QGuiApplicationPrivate::focus_window == qWindow)
337 focusHijackingPopupHidden();
338 setShownFromOhos(
false);
348 qWindow->setVisible(
true);
349 setShownFromOhos(
true);
350 startAsyncWaitForNodeResizeIfNeeded();
360 auto *qWindow = window();
363 "Window status changed, window: %p(%s) status: %d",
365 qPrintable(qWindow->objectName()),
370 if (m_lastWindowStatusType == evt.type
371 && m_lastWindowStatusType == QOhosWindowProxy::WindowStatusType::FULL_SCREEN
372 && !(m_view->viewType() == QOhosView::ViewType::MainWindow
373 && !QOhosSettings::instance().isWindowPcModeEnabled())) {
374 qCDebug(QtForOhos,
"Window status is the same as the previous one");
378 Qt::WindowStates windowStatesToSet = windowStates();
379 m_lastWindowStatusType = evt.type;
384 case QOhosWindowProxy::WindowStatusType::FULL_SCREEN:
385 case QOhosWindowProxy::WindowStatusType::MAXIMIZE:
386 windowStatesToSet = m_view->isFullscreenImmersiveModeEnabled()
387 ? Qt::WindowState::WindowFullScreen
388 : Qt::WindowState::WindowMaximized;
391 if (m_view->consumePendingSelfMinimizeEcho()) {
401 windowStatesToSet.setFlag(Qt::WindowState::WindowMinimized);
403 case QOhosWindowProxy::WindowStatusType::UNDEFINED:
404 case QOhosWindowProxy::WindowStatusType::FLOATING:
405 case QOhosWindowProxy::WindowStatusType::SPLIT_SCREEN:
406 windowStatesToSet = Qt::WindowState::WindowNoState;
410 setWindowStateFromOhos(windowStatesToSet);
416 startAsyncWaitForNodeResizeIfNeeded();
421 auto *qWindow = window();
424 "Window %p(%s) visibility changed: %s",
426 qPrintable(qWindow->objectName()),
427 visible ?
"true" :
"false");
428 if (visible && m_windowMask.has_value())
429 m_view->setWindowMask(QOhosWindowProxy::WindowMask{m_windowMask.value()});
431 setShownFromOhos(visible);
436 m_shownFromOhos = shown;
438 activateIfDeferredUntilExposed();
446 if (
auto deferredActivationEvent = std::exchange(m_activationEventDeferredUntilExposed, std::nullopt))
447 handleWindowEvent(*deferredActivationEvent);
452 const QOhosWindowProxy::AvoidArea &systemAvoidArea)
454 const auto &cached = m_avoidAreaCache[avoidAreaType];
456 bool actuallyChanged =
457 cached.visible != systemAvoidArea.visible
458 || cached.leftRect != systemAvoidArea.leftRect
459 || cached.rightRect != systemAvoidArea.rightRect
460 || cached.bottomRect != systemAvoidArea.bottomRect
461 || cached.topRect != systemAvoidArea.topRect;
463 if (actuallyChanged) {
464 m_avoidAreaCache[avoidAreaType] = systemAvoidArea;
465 qCDebug(QtForOhos) <<
"Avoid area changed:"
466 <<
static_cast<
int>(avoidAreaType)
467 <<
"visible:" << systemAvoidArea.visible
468 <<
"top:" << systemAvoidArea.topRect
469 <<
"left:" << systemAvoidArea.leftRect
470 <<
"right:" << systemAvoidArea.rightRect
471 <<
"bottom:" << systemAvoidArea.bottomRect;
472 startAsyncWaitForNodeResizeIfNeeded();
476void QOhosFloatingWindow::handleSurfaceStatusChanged(
const std::optional<QSize> &optSurfaceSize)
478 m_optLastSurfaceSize = optSurfaceSize;
479 bool hasSurface = m_view->surfaceOrNull() !=
nullptr;
480 if (m_view->viewType() == QOhosView::ViewType::EmbeddedWindow) {
482 }
else if (m_shownFromOhos && hasSurface !=
isExposed()) {
484 activateIfDeferredUntilExposed();
488 startAsyncWaitForNodeResizeIfNeeded();
494 startAsyncWaitForNodeResizeIfNeeded();
498 const QOhosWindowProxy::RectChangeOptions &rectChangeOptions)
503 <<
"windowRectChanged window:" << window()
504 <<
"rect:" << rectChangeOptions.rect
505 <<
"reason:" <<
static_cast<
int>(rectChangeOptions.reason);
507 if (rectChangeOptions.rect.size() != lastRequestedWindowFrameGeometry().size())
508 m_optSizeBeforeResizeRequest.reset();
510 startAsyncWaitForNodeResizeIfNeeded();
512 if (isWindowRotatedByTabletScreenRotation(window(), rectChangeOptions))
513 needsCloseAllActivePopups =
true;
515 if (needsCloseAllActivePopups)
521 if (event->type() == QEvent::WindowUnblocked) {
522 auto deferredActivationEvent =
523 std::exchange(m_activationEventDeferredUntilWindowUnblocked, std::nullopt);
524 const QWindow *windowHoldingFocus = QGuiApplicationPrivate::focus_window;
525 bool noVisibleWindowHoldsFocus =
526 windowHoldingFocus ==
nullptr || !windowHoldingFocus->isVisible();
527 if (deferredActivationEvent && noVisibleWindowHoldsFocus)
528 handleWindowEvent(*deferredActivationEvent);
531 if (event->type() == QEvent::Timer) {
532 auto *timerEvent =
static_cast<QTimerEvent *>(event);
533 if (m_view && timerEvent->timerId() == m_geometryChangeTimer.timerId()) {
534 auto syntheticEvent = m_view->nodeAreaInfo();
535 handleNodeResizeEvent(syntheticEvent);
539 return QOhosPlatformWindow::windowEvent(event);
544 constexpr auto geometryChangeEventTimeoutMs = std::chrono::milliseconds(16);
546 if (!m_geometryChangeTimer.isActive()) {
547 m_geometryChangeTimer.start(
548 geometryChangeEventTimeoutMs.count(),
556 m_geometryChangeTimer.stop();
558 if (Q_UNLIKELY(!m_view))
561 if (m_view->viewType() != QOhosView::ViewType::EmbeddedWindow) {
562 const QSize size = areaChangeEvent.screenGeometryPixels.size();
566 if (size != m_optSizeBeforeResizeRequest) {
567 m_optSizeBeforeResizeRequest.reset();
568 setWindowGeometryFromOhos(QRect(areaChangeEvent.globalRelativeOffsetPixels, size));
572 updateSafeAreaMargins();
580 for (
const QRect &cutout : cutoutRects) {
581 if (cutout.isEmpty() || !cutout.intersects(windowRect))
583 const int distTop = cutout.top() - windowRect.top();
584 const int distBottom = windowRect.bottom() - cutout.bottom();
585 const int distLeft = cutout.left() - windowRect.left();
586 const int distRight = windowRect.right() - cutout.right();
587 int nearest = qMin(qMin(distTop, distBottom), qMin(distLeft, distRight));
588 if (nearest == distTop)
589 margins.setTop(qMax(margins.top(), cutout.bottom() + 1 - windowRect.top()));
590 else if (nearest == distBottom)
591 margins.setBottom(qMax(margins.bottom(), windowRect.bottom() + 1 - cutout.top()));
592 else if (nearest == distLeft)
593 margins.setLeft(qMax(margins.left(), cutout.right() + 1 - windowRect.left()));
595 margins.setRight(qMax(margins.right(), windowRect.right() + 1 - cutout.left()));
604 static constexpr QOhosWindowProxy::
AvoidAreaType kSafeAreaContributors[] = {
613 const QRect frame = m_view->viewGeometry().frameGeometry;
614 const QRect content = m_view->nodeScreenGeometryPixels();
615 if (!frame.contains(content))
617 const int alreadyTop = content.top() - frame.top();
618 const int alreadyLeft = content.left() - frame.left();
619 const int alreadyRight = frame.right() - content.right();
620 const int alreadyBottom = frame.bottom() - content.bottom();
623 for (
auto type : kSafeAreaContributors) {
624 const QMargins m = m_view->avoidAreaMargins(type);
625 combined.setTop(qMax(combined.top(), qMax(0, m.top() - alreadyTop)));
626 combined.setLeft(qMax(combined.left(), qMax(0, m.left() - alreadyLeft)));
627 combined.setRight(qMax(combined.right(), qMax(0, m.right() - alreadyRight)));
628 combined.setBottom(qMax(combined.bottom(), qMax(0, m.bottom() - alreadyBottom)));
634 const QMargins cutout = cutoutMarginsForWindow(m_view->displayCutoutRects(), content);
635 combined.setTop(qMax(combined.top(), cutout.top()));
636 combined.setLeft(qMax(combined.left(), cutout.left()));
637 combined.setRight(qMax(combined.right(), cutout.right()));
638 combined.setBottom(qMax(combined.bottom(), cutout.bottom()));
640 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)