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
window_manager.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 <qarkui/window_manager.h>
5
6#include <cstdint>
7#include <qohosdisplayinfo.h>
8#include <multimodalinput/oh_input_manager.h>
9#include <qohosplugincore.h>
10#include <qohosutils.h>
11#include <render/qohosbatchingrequestshandler.h>
12#include <window_manager/oh_display_info.h>
13#include <window_manager/oh_window_comm.h>
14#include <window_manager/oh_window_event_filter.h>
15#include <memory>
16#include <tuple>
17
19
20namespace QArkUi {
21
22namespace {
23
24using JsDisplayId = QOhosDisplayInfo::JsDisplayId;
25
26struct MouseEventFilterRegistryTraits
27{
28 using RawEventType = ::Input_MouseEvent;
29 using MappedEventType = MouseEvent;
30
31 static constexpr auto registerEventFilterFunc = ::OH_NativeWindowManager_RegisterMouseEventFilter;
32 static constexpr auto unregisterEventFilterFunc = ::OH_NativeWindowManager_UnregisterMouseEventFilter;
33
34 static JsWindowId extractWindowIdFromEvent(RawEventType *event);
35};
36
37struct KeyEventFilterRegistryTraits
38{
39 using RawEventType = ::Input_KeyEvent;
40 using MappedEventType = KeyEvent;
41
42 static constexpr auto registerEventFilterFunc = ::OH_NativeWindowManager_RegisterKeyEventFilter;
43 static constexpr auto unregisterEventFilterFunc = ::OH_NativeWindowManager_UnregisterKeyEventFilter;
44
45 static JsWindowId extractWindowIdFromEvent(RawEventType *event);
46};
47
48struct TouchEventFilterRegistryTraits
49{
50 using RawEventType = ::Input_TouchEvent;
51 using MappedEventType = TouchEvent;
52
53 static constexpr auto registerEventFilterFunc = ::OH_NativeWindowManager_RegisterTouchEventFilter;
54 static constexpr auto unregisterEventFilterFunc = ::OH_NativeWindowManager_UnregisterTouchEventFilter;
55
56 static JsWindowId extractWindowIdFromEvent(RawEventType *event);
57};
58
59template<typename Traits>
60class EventConsumersMap
61{
62public:
63 using RawEventType = typename Traits::RawEventType;
64 using MappedEventType = typename Traits::MappedEventType;
65
66 static EventConsumersMap<Traits> &instance();
67
68 EventConsumersMap(const EventConsumersMap &) = delete;
69 EventConsumersMap(EventConsumersMap &&) = delete;
70 EventConsumersMap &operator=(const EventConsumersMap &) = delete;
71 EventConsumersMap &operator=(EventConsumersMap &&) = delete;
72
73 std::shared_ptr<void> registerEventsConsumer(
74 JsWindowId jsWindowId,
75 QOhosConsumer<const MappedEventType &> eventsConsumer);
76
77private:
78 static bool filterEvent(typename Traits::RawEventType *event);
79 void consumeEvent(JsWindowId jsWindowId, typename Traits::MappedEventType mappedEvent);
80
81 EventConsumersMap();
82
83 QOhosConsumer<std::tuple<JsWindowId, MappedEventType>> m_mtSafeEventsConsumerProxy;
84 std::map<JsWindowId, std::shared_ptr<QOhosConsumer<const MappedEventType &>>> m_consumersMap;
85};
86
87using MouseEventFilterRegistry = EventConsumersMap<MouseEventFilterRegistryTraits>;
88using KeyEventFilterRegistry = EventConsumersMap<KeyEventFilterRegistryTraits>;
89using TouchEventFilterRegistry = EventConsumersMap<TouchEventFilterRegistryTraits>;
90
91JsWindowId MouseEventFilterRegistryTraits::extractWindowIdFromEvent(::Input_MouseEvent *event)
92{
93 return JsWindowId(::OH_Input_GetMouseEventWindowId(event));
94}
95
96JsWindowId KeyEventFilterRegistryTraits::extractWindowIdFromEvent(::Input_KeyEvent *event)
97{
98 return JsWindowId(::OH_Input_GetKeyEventWindowId(event));
99}
100
101JsWindowId TouchEventFilterRegistryTraits::extractWindowIdFromEvent(::Input_TouchEvent *event)
102{
103 return JsWindowId(::OH_Input_GetTouchEventWindowId(event));
104}
105
106template<typename Traits>
107EventConsumersMap<Traits> &EventConsumersMap<Traits>::instance()
108{
109 static EventConsumersMap<Traits> eventConsumersMap;
110 return eventConsumersMap;
111}
112
113template<typename Traits>
114EventConsumersMap<Traits>::EventConsumersMap()
115 : m_mtSafeEventsConsumerProxy(
116 makeQtOhosSimpleBatchingMTRequestsHandler<std::tuple<JsWindowId, MappedEventType>>(
117 [](std::function<void()> task) {
118 QtOhos::invokeInJsThread(
119 [task = std::move(task)](QtOhos::JsState &) {
120 task();
121 });
122 },
123 [this](std::vector<std::tuple<JsWindowId, MappedEventType>> eventsBatch) {
124 for (const auto &event : eventsBatch)
125 consumeEvent(std::get<JsWindowId>(event), std::get<MappedEventType>(event));
126 }))
127{
128}
129
130template<typename Traits>
131std::shared_ptr<void> EventConsumersMap<Traits>::registerEventsConsumer(
132 JsWindowId jsWindowId,
133 QOhosConsumer<const MappedEventType &> eventsConsumer)
134{
135 if (m_consumersMap.find(jsWindowId) != m_consumersMap.end()) {
136 qOhosReportFatalErrorAndAbort(
137 "%s: Duplicate event consumer for jsWindowId: %f", Q_FUNC_INFO, jsWindowId.value());
138 }
139
140 auto errorCode = (*Traits::registerEventFilterFunc)(
141 static_cast<std::int32_t>(jsWindowId.value()), &EventConsumersMap<Traits>::filterEvent);
142 if (errorCode != ::OK) {
143 qOhosReportFatalErrorAndAbort(
144 "%s: failed to register event filter with error: %d",
145 Q_FUNC_INFO, errorCode);
146 }
147 auto unregisterHandle = QtOhos::makeDestroyNotifier([jsWindowId]() {
148 qOhosPrintfWarning("%s - %f", Q_FUNC_INFO, jsWindowId.value());
149 (*Traits::unregisterEventFilterFunc)(static_cast<std::int32_t>(jsWindowId.value()));
150 });
151
152 m_consumersMap[jsWindowId] =
153 QtOhos::makeSharedPtrWithAttachedExtraData(
154 QtOhos::moveToSharedPtr(std::move(eventsConsumer)),
155 std::move(unregisterHandle));
156
157 return QtOhos::makeDestroyNotifier([this, jsWindowId]() {
158 qOhosPrintfWarning("%s: %f", Q_FUNC_INFO, jsWindowId.value());
159 std::ignore = m_consumersMap.erase(jsWindowId);
160 });
161}
162
163template<typename Traits>
164bool EventConsumersMap<Traits>::filterEvent(typename Traits::RawEventType *event)
165{
166 auto jsWindowId = Traits::extractWindowIdFromEvent(event);
167 auto optMappedEvent = MappedEventType::createFromNativeEvent(event);
168 if (optMappedEvent.hasValue())
169 instance().m_mtSafeEventsConsumerProxy(std::make_tuple(jsWindowId, optMappedEvent.value()));
170 else
171 qOhosPrintfWarning("%s: jsWindowId: %f, Failed to map native event type", Q_FUNC_INFO, jsWindowId.value());
172 return false;
173}
174
175template<typename Traits>
176void EventConsumersMap<Traits>::consumeEvent(JsWindowId jsWindowId, MappedEventType mappedEvent)
177{
178 auto consumerIter = m_consumersMap.find(jsWindowId);
179 if (consumerIter == m_consumersMap.end()) {
180 qOhosPrintfWarning(
181 "%s: received event for jsWindowId: %f which does not contain events consumer",
182 Q_FUNC_INFO, jsWindowId.value());
183 return;
184 }
185
186 auto &eventConsumerFunc = *(consumerIter->second);
187 (eventConsumerFunc)(mappedEvent);
188}
189
190}
191
193 JsWindowId jsWindowId,
194 QOhosConsumer<const MouseEvent &> eventsConsumer)
195{
196 return MouseEventFilterRegistry::instance()
197 .registerEventsConsumer(jsWindowId, std::move(eventsConsumer));
198}
199
201 JsWindowId jsWindowId,
202 QOhosConsumer<const KeyEvent &> eventsConsumer)
203{
204 return KeyEventFilterRegistry::instance()
205 .registerEventsConsumer(jsWindowId, std::move(eventsConsumer));
206}
207
209 JsWindowId jsWindowId,
210 QOhosConsumer<const TouchEvent &> eventsConsumer)
211{
212 return TouchEventFilterRegistry::instance()
213 .registerEventsConsumer(jsWindowId, std::move(eventsConsumer));
214}
215
216}
217
218QT_END_NAMESPACE
std::shared_ptr< void > registerMouseEventsConsumer(JsWindowId jsWindowId, QOhosConsumer< const MouseEvent & > eventsConsumer)
std::shared_ptr< void > registerKeyEventsConsumer(JsWindowId jsWindowId, QOhosConsumer< const KeyEvent & > eventsConsumer)
std::shared_ptr< void > registerTouchEventsConsumer(JsWindowId jsWindowId, QOhosConsumer< const TouchEvent & > eventsConsumer)
Combined button and popup list for selecting options.