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>
28 return !QOhosSettings::instance().isWindowPcModeEnabled()
29 && rectChangeOptions.rect.isValid()
30 && window->geometry() != rectChangeOptions.rect
31 && rectChangeOptions.reason == QOhosWindowProxy::RectChangeReason::UNDEFINED;
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);
72 auto *targetScreen = QOhosPlatformWindow::screenForGeometry(rect.marginsAdded(frameMargins()));
73 if (targetScreen !=
nullptr && targetScreen != currentScreen)
74 QWindowSystemInterface::handleWindowScreenChanged(window(), targetScreen->screen());
76 if (view !=
nullptr) {
77 auto frameGeometry = rect.marginsAdded(frameMargins());
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();
93 startAsyncWaitForNodeResizeIfNeeded();
98 auto windowObjectName = window()->objectName();
101 "%s: winId called for window named: \"%s\"",
103 windowObjectName.toStdString().c_str());
105 return reinterpret_cast<WId>(m_view->viewWindowId());
111 if (view !=
nullptr) {
113 window()->requestUpdate();
120 if (view !=
nullptr) {
122 window()->requestUpdate();
140 m_view = QOhosView::createForWindow(
this, propertiesProvider());
142 auto *qWindow = window();
148 if (m_view->viewType() == QOhosView::ViewType::MainWindow
149 && !QOhosSettings::instance().isWindowPcModeEnabled()
150 && !m_lastWindowStatusType.has_value()) {
151 m_lastWindowStatusType = QOhosWindowProxy::WindowStatusType::FULL_SCREEN;
155 m_view.get(), &QOhosView::externalContentInteractionDetected,
156 qWindow, &QOhosPlatformWindow::closeAllActivePopups);
159 m_view.get(), &QOhosView::nodeAreaChanged, m_view.get(),
160 [
this](QArkUi::QQtEmbeddedWindowNode::NodeAreaInfo event) {
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();
293 case QOhosWindowProxy::WindowEventType::WINDOW_ACTIVE:
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);
315 case QOhosWindowProxy::WindowEventType::WINDOW_INACTIVE:
316 if (!windowAcceptsFocusAndInput)
318 if (shouldClearQtFocusOnSystemFocusLoss(qWindow) && !anyQtWindowHoldsSystemFocus())
319 QWindowSystemInterface::handleFocusWindowChanged(
nullptr, Qt::ActiveWindowFocusReason);
322 case QOhosWindowProxy::WindowEventType::WINDOW_HIDDEN:
323 if (!checkWindowAcceptsFocus() && QGuiApplicationPrivate::focus_window == qWindow)
324 focusHijackingPopupHidden();
327 case QOhosWindowProxy::WindowEventType::WINDOW_SHOWN:
334 if (previousWindowEventType == QOhosWindowProxy::WindowEventType::WINDOW_HIDDEN && !qWindow->isVisible())
335 qWindow->setVisible(
true);
337 startAsyncWaitForNodeResizeIfNeeded();
339 case QOhosWindowProxy::WindowEventType::WINDOW_DESTROYED:
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;
377 case QOhosWindowProxy::WindowStatusType::MINIMIZE:
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()});
422 QOhosWindowProxy::AvoidAreaType avoidAreaType,
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) {
456 startAsyncWaitForNodeResizeIfNeeded();
462 startAsyncWaitForNodeResizeIfNeeded();
466 const QOhosWindowProxy::RectChangeOptions &rectChangeOptions)
468 bool needsCloseAllActivePopups = rectChangeOptions.reason == QOhosWindowProxy::RectChangeReason::DRAG_START;
471 <<
"windowRectChanged window:" << window()
472 <<
"rect:" << rectChangeOptions.rect
473 <<
"reason:" <<
static_cast<
int>(rectChangeOptions.reason);
475 startAsyncWaitForNodeResizeIfNeeded();
477 if (isWindowRotatedByTabletScreenRotation(window(), rectChangeOptions))
478 needsCloseAllActivePopups =
true;
480 if (needsCloseAllActivePopups)
486 if (event->type() == QEvent::WindowUnblocked) {
487 auto deferredActivationEvent =
488 std::exchange(m_activationEventDeferredUntilWindowUnblocked, std::nullopt);
489 const QWindow *windowHoldingFocus = QGuiApplicationPrivate::focus_window;
490 bool noVisibleWindowHoldsFocus =
491 windowHoldingFocus ==
nullptr || !windowHoldingFocus->isVisible();
492 if (deferredActivationEvent && noVisibleWindowHoldsFocus)
493 handleWindowEvent(*deferredActivationEvent);
496 if (event->type() == QEvent::Timer) {
497 auto *timerEvent =
static_cast<QTimerEvent *>(event);
498 if (m_view && timerEvent->timerId() == m_geometryChangeTimer.timerId()) {
499 auto syntheticEvent = m_view->nodeAreaInfo();
500 handleNodeResizeEvent(syntheticEvent);
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 if (m_view->viewType() != QOhosView::ViewType::EmbeddedWindow)
527 setWindowGeometryFromOhos(
528 QRect(areaChangeEvent.globalRelativeOffsetPixels, areaChangeEvent.screenGeometryPixels.size()));
530 updateSafeAreaMargins();
538 for (
const QRect &cutout : cutoutRects) {
539 if (cutout.isEmpty() || !cutout.intersects(windowRect))
541 const int distTop = cutout.top() - windowRect.top();
542 const int distBottom = windowRect.bottom() - cutout.bottom();
543 const int distLeft = cutout.left() - windowRect.left();
544 const int distRight = windowRect.right() - cutout.right();
545 int nearest = qMin(qMin(distTop, distBottom), qMin(distLeft, distRight));
546 if (nearest == distTop)
547 margins.setTop(qMax(margins.top(), cutout.bottom() + 1 - windowRect.top()));
548 else if (nearest == distBottom)
549 margins.setBottom(qMax(margins.bottom(), windowRect.bottom() + 1 - cutout.top()));
550 else if (nearest == distLeft)
551 margins.setLeft(qMax(margins.left(), cutout.right() + 1 - windowRect.left()));
553 margins.setRight(qMax(margins.right(), windowRect.right() + 1 - cutout.left()));
562 static constexpr QOhosWindowProxy::AvoidAreaType kSafeAreaContributors[] = {
563 QOhosWindowProxy::AvoidAreaType::TYPE_SYSTEM,
564 QOhosWindowProxy::AvoidAreaType::TYPE_NAVIGATION_INDICATOR,
571 const QRect frame = m_view->viewGeometry().frameGeometry;
572 const QRect content = m_view->nodeScreenGeometryPixels();
573 const int alreadyTop = content.top() - frame.top();
574 const int alreadyLeft = content.left() - frame.left();
575 const int alreadyRight = frame.right() - content.right();
576 const int alreadyBottom = frame.bottom() - content.bottom();
579 for (
auto type : kSafeAreaContributors) {
580 const QMargins m = m_view->avoidAreaMargins(type);
581 combined.setTop(qMax(combined.top(), qMax(0, m.top() - alreadyTop)));
582 combined.setLeft(qMax(combined.left(), qMax(0, m.left() - alreadyLeft)));
583 combined.setRight(qMax(combined.right(), qMax(0, m.right() - alreadyRight)));
584 combined.setBottom(qMax(combined.bottom(), qMax(0, m.bottom() - alreadyBottom)));
590 const QMargins cutout = cutoutMarginsForWindow(m_view->displayCutoutRects(), content);
591 combined.setTop(qMax(combined.top(), cutout.top()));
592 combined.setLeft(qMax(combined.left(), cutout.left()));
593 combined.setRight(qMax(combined.right(), cutout.right()));
594 combined.setBottom(qMax(combined.bottom(), cutout.bottom()));
596 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.
QOhosSurface * surfaceOrNull() const
void setWindowMask(const QOhosWindowProxy::WindowMask &windowMask)
QtOhos::enums::ohos::window::WindowEventType WindowEventType
static QWindowProxyRegistry & instance()
Combined button and popup list for selecting options.
bool shouldClearQtFocusOnSystemFocusLoss(QWindow *windowLosingSystemFocus)
bool anyQtWindowHoldsSystemFocus()
bool isWindowRotatedByTabletScreenRotation(QWindow *window, QOhosWindowProxy::RectChangeOptions rectChangeOptions)
static QMargins cutoutMarginsForWindow(const QList< QRect > &cutoutRects, const QRect &windowRect)