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);
92 m_view->showImmediate();
97 auto windowObjectName = window()->objectName();
100 "%s: winId called for window named: \"%s\"",
102 windowObjectName.toStdString().c_str());
104 return reinterpret_cast<WId>(m_view->viewWindowId());
110 if (view !=
nullptr) {
112 window()->requestUpdate();
119 if (view !=
nullptr) {
121 window()->requestUpdate();
139 m_view = QOhosView::createForWindow(
this, propertiesProvider());
141 auto *qWindow = window();
147 if (m_view->viewType() == QOhosView::ViewType::MainWindow
148 && !QOhosSettings::instance().isWindowPcModeEnabled()
149 && !m_lastWindowStatusType.has_value()) {
150 m_lastWindowStatusType = QOhosWindowProxy::WindowStatusType::FULL_SCREEN;
154 m_view.get(), &QOhosView::externalContentInteractionDetected,
155 qWindow, &QOhosPlatformWindow::closeAllActivePopups);
158 m_view.get(), &QOhosView::nodeAreaChanged, m_view.get(),
159 [
this](QArkUi::QQtEmbeddedWindowNode::NodeAreaInfo event) {
160 if (m_view->viewType() == QOhosView::ViewType::EmbeddedWindow)
161 handleNodeResizeEvent(event);
165 m_view.get(), &QOhosView::windowEvent,
167 [
this](QOhosWindowProxy::WindowEvent evt) { handleWindowEvent(evt); });
170 m_view.get(), &QOhosView::windowStatusChange,
172 [
this](QOhosWindowProxy::WindowStatus evt) { handleWindowStatusChange(evt); });
175 m_view.get(), &QOhosView::windowVisibilityChange,
177 [
this](
bool visible) { handleWindowVisibilityChange(visible); });
179 bool monitorAvoidAreaChange =
180 !(isHandheldDeviceType() && m_view->viewType() == QOhosView::ViewType::SubWindow);
182 if (monitorAvoidAreaChange) {
184 m_view.get(), &QOhosView::avoidAreaChanged,
186 [
this](QOhosWindowProxy::AvoidAreaType avoidAreaType,
187 const QOhosWindowProxy::AvoidArea &systemAvoidArea) {
188 handleAvoidAreaChanged(avoidAreaType, systemAvoidArea);
193 m_view.get(), &QOhosView::windowRectChangedInGlobalDisplay,
195 [
this](
const QOhosWindowProxy::RectChangeOptions &rectChangeOptions) {
196 handleWindowRectChanged(rectChangeOptions);
199 QObject::connect(qWindow, &QWindow::modalityChanged, m_view.get(), &QOhosView::setModality);
202 m_view.get(), &QOhosView::surfaceStatusChanged,
204 [
this](
const std::optional<QSize> &optSurfaceSize) { handleSurfaceStatusChanged(optSurfaceSize); });
206 QObject::connect(qWindow, &QWindow::windowTitleChanged, m_view.get(), &QOhosView::setTitle);
209 m_view.get(), &QOhosView::windowDisplayIdChanged,
211 [
this](QOhosDisplayInfo::JsDisplayId displayId) { handleWindowDisplayIdChanged(displayId); });
217 if (view !=
nullptr && m_cursor.has_value())
218 view->setCursor(m_cursor.value());
222 Qt::WindowFlags previousWindowFlags, Qt::WindowFlags currentWindowFlags)
228 view->handleWindowFlagsChange(previousWindowFlags, currentWindowFlags);
232 Qt::WindowStates oldWindowState, Qt::WindowStates currentWindowState)
238 view->handleWindowStateChange(oldWindowState, currentWindowState);
243 QWindowSystemInterface::handleFocusWindowChanged(window(), Qt::PopupFocusReason);
249 QWindowSystemInterface::handleFocusWindowChanged(
250 !systemFocusedWindows.empty() ? systemFocusedWindows.front() :
nullptr,
251 Qt::ActiveWindowFocusReason);
256 m_windowMask = region;
275 if (windowFlags().testFlag(Qt::WindowDoesNotAcceptFocus) && window()->type() == Qt::Popup) {
276 internalHijackSystemFocusAsPopup();
285 auto *qWindow = window();
287 auto previousWindowEventType = std::exchange(m_lastWindowEventType, evt.type);
289 if (evt.type != QOhosWindowProxy::WindowEventType::WINDOW_SHOWN)
290 m_activationEventDeferredUntilWindowUnblocked.reset();
295 QWindow *modalWindow =
nullptr;
296 if (QGuiApplicationPrivate::instance()->isWindowBlocked(qWindow, &modalWindow)
297 && qWindow != modalWindow) {
298 if (qWindow->isTopLevel())
299 m_activationEventDeferredUntilWindowUnblocked = evt;
300 modalWindow->requestActivate();
308 restoreWindowCurrentCursorIfNeeded();
309 if (windowAcceptsFocusAndInput) {
310 QWindowSystemInterface::handleFocusWindowChanged(qWindow, Qt::ActiveWindowFocusReason);
316 if (!windowAcceptsFocusAndInput)
318 if (shouldClearQtFocusOnSystemFocusLoss(qWindow) && !anyQtWindowHoldsSystemFocus())
319 QWindowSystemInterface::handleFocusWindowChanged(
nullptr, Qt::ActiveWindowFocusReason);
323 if (!checkWindowAcceptsFocus() && QGuiApplicationPrivate::focus_window == qWindow)
324 focusHijackingPopupHidden();
335 qWindow->setVisible(
true);
337 startAsyncWaitForNodeResizeIfNeeded();
347 auto *qWindow = window();
350 "Window status changed, window: %p(%s) status: %d",
352 qPrintable(qWindow->objectName()),
357 if (m_lastWindowStatusType == evt.type
358 && m_lastWindowStatusType == QOhosWindowProxy::WindowStatusType::FULL_SCREEN
359 && !(m_view->viewType() == QOhosView::ViewType::MainWindow
360 && !QOhosSettings::instance().isWindowPcModeEnabled())) {
361 qCDebug(QtForOhos,
"Window status is the same as the previous one");
365 Qt::WindowStates windowStatesToSet = windowStates();
366 m_lastWindowStatusType = evt.type;
371 case QOhosWindowProxy::WindowStatusType::FULL_SCREEN:
372 case QOhosWindowProxy::WindowStatusType::MAXIMIZE:
373 windowStatesToSet = m_view->isFullscreenImmersiveModeEnabled()
374 ? Qt::WindowState::WindowFullScreen
375 : Qt::WindowState::WindowMaximized;
378 if (m_view->consumePendingSelfMinimizeEcho()) {
388 windowStatesToSet.setFlag(Qt::WindowState::WindowMinimized);
390 case QOhosWindowProxy::WindowStatusType::UNDEFINED:
391 case QOhosWindowProxy::WindowStatusType::FLOATING:
392 case QOhosWindowProxy::WindowStatusType::SPLIT_SCREEN:
393 windowStatesToSet = Qt::WindowState::WindowNoState;
397 setWindowStateFromOhos(windowStatesToSet);
403 startAsyncWaitForNodeResizeIfNeeded();
408 auto *qWindow = window();
411 "Window %p(%s) visibility changed: %s",
413 qPrintable(qWindow->objectName()),
414 visible ?
"true" :
"false");
415 if (visible && m_windowMask.has_value())
416 m_view->setWindowMask(QOhosWindowProxy::WindowMask{m_windowMask.value()});
423 const QOhosWindowProxy::AvoidArea &systemAvoidArea)
425 const auto &cached = m_avoidAreaCache[avoidAreaType];
427 bool actuallyChanged =
428 cached.visible != systemAvoidArea.visible
429 || cached.leftRect != systemAvoidArea.leftRect
430 || cached.rightRect != systemAvoidArea.rightRect
431 || cached.bottomRect != systemAvoidArea.bottomRect
432 || cached.topRect != systemAvoidArea.topRect;
434 if (actuallyChanged) {
435 m_avoidAreaCache[avoidAreaType] = systemAvoidArea;
436 qCDebug(QtForOhos) <<
"Avoid area changed:"
437 <<
static_cast<
int>(avoidAreaType)
438 <<
"visible:" << systemAvoidArea.visible
439 <<
"top:" << systemAvoidArea.topRect
440 <<
"left:" << systemAvoidArea.leftRect
441 <<
"right:" << systemAvoidArea.rightRect
442 <<
"bottom:" << systemAvoidArea.bottomRect;
443 startAsyncWaitForNodeResizeIfNeeded();
447void QOhosFloatingWindow::handleSurfaceStatusChanged(
const std::optional<QSize> &optSurfaceSize)
449 m_optLastSurfaceSize = optSurfaceSize;
450 bool hasSurface = m_view->surfaceOrNull() !=
nullptr;
451 if (m_view->viewType() == QOhosView::ViewType::EmbeddedWindow)
458 startAsyncWaitForNodeResizeIfNeeded();
462 const QOhosWindowProxy::RectChangeOptions &rectChangeOptions)
467 <<
"windowRectChanged window:" << window()
468 <<
"rect:" << rectChangeOptions.rect
469 <<
"reason:" <<
static_cast<
int>(rectChangeOptions.reason);
471 startAsyncWaitForNodeResizeIfNeeded();
473 if (isWindowRotatedByTabletScreenRotation(window(), rectChangeOptions))
474 needsCloseAllActivePopups =
true;
476 if (needsCloseAllActivePopups)
482 if (event->type() == QEvent::WindowUnblocked) {
483 auto deferredActivationEvent =
484 std::exchange(m_activationEventDeferredUntilWindowUnblocked, std::nullopt);
485 const QWindow *windowHoldingFocus = QGuiApplicationPrivate::focus_window;
486 bool noVisibleWindowHoldsFocus =
487 windowHoldingFocus ==
nullptr || !windowHoldingFocus->isVisible();
488 if (deferredActivationEvent && noVisibleWindowHoldsFocus)
489 handleWindowEvent(*deferredActivationEvent);
492 if (event->type() == QEvent::Timer) {
493 auto *timerEvent =
static_cast<QTimerEvent *>(event);
494 if (m_view && timerEvent->timerId() == m_geometryChangeTimer.timerId()) {
499 if (m_view->isNodeLaidOut())
500 handleNodeResizeEvent(m_view->nodeAreaInfo());
504 return QOhosPlatformWindow::windowEvent(event);
509 constexpr auto geometryChangeEventTimeoutMs = std::chrono::milliseconds(16);
511 if (!m_geometryChangeTimer.isActive()) {
512 m_geometryChangeTimer.start(
513 geometryChangeEventTimeoutMs.count(),
521 m_geometryChangeTimer.stop();
523 if (Q_UNLIKELY(!m_view))
526 const QPoint pos = m_view->viewType() == QOhosView::ViewType::EmbeddedWindow
527 ? areaChangeEvent.parentRelativeOffsetPixels
528 : areaChangeEvent.globalRelativeOffsetPixels;
529 setWindowGeometryFromOhos(QRect(pos, areaChangeEvent.screenGeometryPixels.size()));
531 updateSafeAreaMargins();
539 for (
const QRect &cutout : cutoutRects) {
540 if (cutout.isEmpty() || !cutout.intersects(windowRect))
542 const int distTop = cutout.top() - windowRect.top();
543 const int distBottom = windowRect.bottom() - cutout.bottom();
544 const int distLeft = cutout.left() - windowRect.left();
545 const int distRight = windowRect.right() - cutout.right();
546 int nearest = qMin(qMin(distTop, distBottom), qMin(distLeft, distRight));
547 if (nearest == distTop)
548 margins.setTop(qMax(margins.top(), cutout.bottom() + 1 - windowRect.top()));
549 else if (nearest == distBottom)
550 margins.setBottom(qMax(margins.bottom(), windowRect.bottom() + 1 - cutout.top()));
551 else if (nearest == distLeft)
552 margins.setLeft(qMax(margins.left(), cutout.right() + 1 - windowRect.left()));
554 margins.setRight(qMax(margins.right(), windowRect.right() + 1 - cutout.left()));
563 static constexpr QOhosWindowProxy::
AvoidAreaType kSafeAreaContributors[] = {
572 const QRect frame = m_view->viewGeometry().frameGeometry;
573 const QRect content = m_view->nodeScreenGeometryPixels();
574 const int alreadyTop = content.top() - frame.top();
575 const int alreadyLeft = content.left() - frame.left();
576 const int alreadyRight = frame.right() - content.right();
577 const int alreadyBottom = frame.bottom() - content.bottom();
580 for (
auto type : kSafeAreaContributors) {
581 const QMargins m = m_view->avoidAreaMargins(type);
582 combined.setTop(qMax(combined.top(), qMax(0, m.top() - alreadyTop)));
583 combined.setLeft(qMax(combined.left(), qMax(0, m.left() - alreadyLeft)));
584 combined.setRight(qMax(combined.right(), qMax(0, m.right() - alreadyRight)));
585 combined.setBottom(qMax(combined.bottom(), qMax(0, m.bottom() - alreadyBottom)));
591 const QMargins cutout = cutoutMarginsForWindow(m_view->displayCutoutRects(), content);
592 combined.setTop(qMax(combined.top(), cutout.top()));
593 combined.setLeft(qMax(combined.left(), cutout.left()));
594 combined.setRight(qMax(combined.right(), cutout.right()));
595 combined.setBottom(qMax(combined.bottom(), cutout.bottom()));
597 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)