Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohosapplicationstatetracker.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qohosapplicationstatetracker.h>
5
6#include <QtCore/private/qohoslogger_p.h>
7#include <QtGui/private/qguiapplication_p.h>
8#include <QtGui/qwindow.h>
9#include <memory>
10#include <qohosplatformwindow.h>
11#include <qohosutils.h>
12#include <qpa/qwindowsysteminterface_p.h>
13#include <render/qohosview.h>
14#include <set>
15#include <tuple>
16
18
19namespace
20{
21
22using WindowSystemEventType = QWindowSystemInterfacePrivate::EventType;
23using WindowSystemEvent = QWindowSystemInterfacePrivate::WindowSystemEvent;
24using WindowStateChangedEvent = QWindowSystemInterfacePrivate::WindowStateChangedEvent;
25using FocusWindowEvent = QWindowSystemInterfacePrivate::FocusWindowEvent;
26using ExposeEvent = QWindowSystemInterfacePrivate::ExposeEvent;
27using ApplicationStateChangedEvent = QWindowSystemInterfacePrivate::ApplicationStateChangedEvent;
28
34
35class ApplicationStateTracker final : public QWindowSystemEventHandler
36{
37public:
38 bool sendEvent(WindowSystemEvent *event) override;
39
40private:
41 ProcessEventResult processWindowStateChangedEvent(WindowStateChangedEvent *event);
42 ProcessEventResult processExposeEvent(ExposeEvent *event);
43 ProcessEventResult processApplicationStateChangedEvent(ApplicationStateChangedEvent *event);
44
45 void startTrackingViewIfNeeded(QOhosView *view);
46 void tryUpdateApplicationState();
47
48 std::set<QOhosView *> m_trackedViews;
49 std::set<QOhosView *> m_visibleViews;
50 std::set<QOhosView *> m_activeViews;
51
52 QOhosOptional<Qt::ApplicationState> m_lastReceivedApplicationState;
53 QOhosOptional<Qt::ApplicationState> m_lastSentApplicationState;
54 QObject m_signalReceiver;
55};
56
58{
59 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(window);
60 return platformWindow != nullptr
61 ? platformWindow->ownedViewOrNull()
62 : nullptr;
63}
64
65ProcessEventResult ApplicationStateTracker::processWindowStateChangedEvent(WindowStateChangedEvent *evt)
66{
67 auto *view = evt->window != nullptr
68 ? mapQWindowToViewOrNull(evt->window)
69 : nullptr;
70
71 if (view == nullptr)
73
74 startTrackingViewIfNeeded(view);
75
76 if (evt->newState.testFlag(Qt::WindowState::WindowActive))
77 std::ignore = m_activeViews.insert(view);
78 else
79 std::ignore = m_activeViews.erase(view);
80
82}
83
84ProcessEventResult ApplicationStateTracker::processExposeEvent(ExposeEvent *evt)
85{
86 auto *view = evt->window != nullptr
87 ? mapQWindowToViewOrNull(evt->window)
88 : nullptr;
89
90 if (view == nullptr)
92
93 startTrackingViewIfNeeded(view);
94
95 if (evt->isExposed)
96 std::ignore = m_visibleViews.insert(view);
97 else
98 std::ignore = m_visibleViews.erase(view);
99
101}
102
103ProcessEventResult ApplicationStateTracker::processApplicationStateChangedEvent(ApplicationStateChangedEvent *evt)
104{
105 auto state = evt->newState;
106 m_lastReceivedApplicationState = state;
108}
109
110bool ApplicationStateTracker::sendEvent(WindowSystemEvent *event)
111{
112 QOhosOptional<ProcessEventResult> processEventResult;
113 switch (event->type) {
114 case WindowSystemEventType::WindowStateChanged:
115 processEventResult = processWindowStateChangedEvent(static_cast<WindowStateChangedEvent *>(event));
116 break;
117 case WindowSystemEventType::Expose:
118 processEventResult = processExposeEvent(static_cast<ExposeEvent *>(event));
119 break;
120 case WindowSystemEventType::ApplicationStateChanged:
121 processEventResult = processApplicationStateChangedEvent(static_cast<ApplicationStateChangedEvent *>(event));
122 break;
123 default:
124 break;
125 }
126
127 bool processEvent = processEventResult != ProcessEventResult::Ignore;
128 if (processEvent)
129 QGuiApplicationPrivate::processWindowSystemEvent(event);
130
131 bool hasPendingEvents = QWindowSystemInterfacePrivate::windowSystemEventsQueued();
132 if (!hasPendingEvents)
133 tryUpdateApplicationState();
134
135 return processEvent;
136}
137
138void ApplicationStateTracker::tryUpdateApplicationState()
139{
140 bool allWindowsInactive = m_activeViews.empty();
141 bool allWindowsHidden = m_visibleViews.empty();
142
143 auto updatedApplicationState =
144 m_lastReceivedApplicationState == Qt::ApplicationSuspended
145 ? Qt::ApplicationSuspended
146 : allWindowsHidden
147 ? Qt::ApplicationHidden
148 : allWindowsInactive
149 ? Qt::ApplicationInactive
150 : Qt::ApplicationActive;
151
152 if (m_lastSentApplicationState == updatedApplicationState)
153 return;
154
155 m_lastSentApplicationState = updatedApplicationState;
156 ApplicationStateChangedEvent eventToSend{updatedApplicationState};
157 QGuiApplicationPrivate::processWindowSystemEvent(&eventToSend);
158}
159
160void ApplicationStateTracker::startTrackingViewIfNeeded(QOhosView *viewToTrack)
161{
162 bool added;
163 std::tie(std::ignore, added) = m_trackedViews.insert(viewToTrack);
164 if (added) {
165 QObject::connect(
166 viewToTrack, &QOhosView::destroyed,
167 &m_signalReceiver, [this, viewToTrack](QObject *) {
168 std::ignore = m_trackedViews.erase(viewToTrack);
169 std::ignore = m_visibleViews.erase(viewToTrack);
170 std::ignore = m_activeViews.erase(viewToTrack);
171 });
172 }
173}
174
175}
176
178{
179 return std::make_shared<ApplicationStateTracker>();
180}
181
182QT_END_NAMESPACE
std::enable_if_t< qohosplugincore_h_detail::isQOhosOptional< QOhosInvokeResult< Func, T > >, QOhosInvokeResult< Func, T > > andThen(Func &&func) const
bool sendEvent(WindowSystemEvent *event) override
Combined button and popup list for selecting options.
QOhosView * mapQWindowToViewOrNull(QWindow *window)
std::shared_ptr< QWindowSystemEventHandler > makeApplicationStateTracker()