1 | // Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). |
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 "inputhandler_p.h" |
5 | |
6 | #include <Qt3DCore/private/qscene_p.h> |
7 | #include <Qt3DInput/qmousehandler.h> |
8 | #include <Qt3DInput/qkeyboardhandler.h> |
9 | #include <Qt3DInput/private/assignkeyboardfocusjob_p.h> |
10 | #include <Qt3DInput/private/inputmanagers_p.h> |
11 | #include <Qt3DInput/private/inputsettings_p.h> |
12 | #include <Qt3DInput/private/qinputdeviceintegration_p.h> |
13 | #include <Qt3DInput/private/qmousehandler_p.h> |
14 | #include <Qt3DInput/private/qkeyboardhandler_p.h> |
15 | #include <Qt3DCore/private/qeventfilterservice_p.h> |
16 | |
17 | |
18 | QT_BEGIN_NAMESPACE |
19 | |
20 | using namespace Qt3DCore; |
21 | |
22 | namespace Qt3DInput { |
23 | namespace Input { |
24 | |
25 | class InternalEventFilter : public QObject |
26 | { |
27 | public: |
28 | explicit InternalEventFilter(QObject *parent = nullptr) : QObject(parent), m_inputHandler(nullptr) { } |
29 | ~InternalEventFilter() override; |
30 | |
31 | void setInputHandler(Qt3DInput::Input::InputHandler *handler) { m_inputHandler = handler; } |
32 | inline Qt3DInput::Input::InputHandler *inputHandler() const { return m_inputHandler; } |
33 | |
34 | protected: |
35 | bool eventFilter(QObject *obj, QEvent *e) override { |
36 | switch (e->type()) { |
37 | case QEvent::MouseMove: |
38 | case QEvent::MouseButtonPress: |
39 | case QEvent::MouseButtonRelease: |
40 | case QEvent::MouseButtonDblClick: |
41 | return processMouseEvent(obj, event: static_cast<QT_PREPEND_NAMESPACE(QMouseEvent) *>(e)); |
42 | case QEvent::HoverMove: { |
43 | const QHoverEvent *he = static_cast<QHoverEvent *>(e); |
44 | auto mouseEvent = QT_PREPEND_NAMESPACE(QMouseEvent)(QEvent::MouseMove, |
45 | he->position(), |
46 | he->globalPosition(), |
47 | Qt::NoButton, Qt::NoButton, |
48 | he->modifiers()); |
49 | return processMouseEvent(obj, event: static_cast<QT_PREPEND_NAMESPACE(QMouseEvent) *>(&mouseEvent)); |
50 | } |
51 | #if QT_CONFIG(wheelevent) |
52 | case QEvent::Wheel: |
53 | return processWheelEvent(obj, event: static_cast<QT_PREPEND_NAMESPACE(QWheelEvent) *>(e)); |
54 | #endif |
55 | case QEvent::KeyPress: |
56 | case QEvent::KeyRelease: |
57 | return processKeyEvent(obj, event: static_cast<QT_PREPEND_NAMESPACE(QKeyEvent) *>(e)); |
58 | default: |
59 | break; |
60 | } |
61 | return false; |
62 | } |
63 | |
64 | bool processMouseEvent(QObject *obj, QT_PREPEND_NAMESPACE(QMouseEvent) *event); |
65 | #if QT_CONFIG(wheelevent) |
66 | bool processWheelEvent(QObject *obj, QT_PREPEND_NAMESPACE(QWheelEvent) *event); |
67 | #endif |
68 | bool processKeyEvent(QObject *obj, QT_PREPEND_NAMESPACE(QKeyEvent) *event); |
69 | |
70 | private: |
71 | Qt3DInput::Input::InputHandler *m_inputHandler; |
72 | }; |
73 | |
74 | |
75 | InputHandler::InputHandler() |
76 | : m_keyboardDeviceManager(new KeyboardDeviceManager()) |
77 | , m_keyboardInputManager(new KeyboardInputManager()) |
78 | , m_mouseDeviceManager(new MouseDeviceManager()) |
79 | , m_mouseInputManager(new MouseInputManager()) |
80 | , m_eventFilter(new InternalEventFilter()) |
81 | , m_axisManager(new AxisManager()) |
82 | , m_axisAccumulatorManager(new AxisAccumulatorManager()) |
83 | , m_actionManager(new ActionManager()) |
84 | , m_axisSettingManager(new AxisSettingManager()) |
85 | , m_actionInputManager(new ActionInputManager()) |
86 | , m_analogAxisInputManager(new AnalogAxisInputManager()) |
87 | , m_buttonAxisInputManager(new ButtonAxisInputManager()) |
88 | , m_inputChordManager(new InputChordManager()) |
89 | , m_inputSequenceManager(new InputSequenceManager()) |
90 | , m_logicalDeviceManager(new LogicalDeviceManager()) |
91 | , m_genericPhysicalDeviceBackendNodeManager(new GenericDeviceBackendNodeManager) |
92 | , m_physicalDeviceProxyManager(new PhysicalDeviceProxyManager()) |
93 | , m_settings(nullptr) |
94 | , m_service(nullptr) |
95 | , m_lastEventSource(nullptr) |
96 | { |
97 | m_eventFilter->setInputHandler(this); |
98 | } |
99 | |
100 | InputHandler::~InputHandler() |
101 | { |
102 | delete m_keyboardDeviceManager; |
103 | delete m_keyboardInputManager; |
104 | delete m_mouseDeviceManager; |
105 | delete m_mouseInputManager; |
106 | delete m_eventFilter; |
107 | delete m_axisManager; |
108 | delete m_axisAccumulatorManager; |
109 | delete m_actionManager; |
110 | delete m_axisSettingManager; |
111 | delete m_analogAxisInputManager; |
112 | delete m_buttonAxisInputManager; |
113 | delete m_actionInputManager; |
114 | delete m_inputChordManager; |
115 | delete m_inputSequenceManager; |
116 | delete m_logicalDeviceManager; |
117 | delete m_genericPhysicalDeviceBackendNodeManager; |
118 | delete m_physicalDeviceProxyManager; |
119 | } |
120 | |
121 | // Called in MainThread (by the EventSourceHelperSetter) |
122 | void InputHandler::registerEventFilters() |
123 | { |
124 | if (m_service) |
125 | m_service->registerEventFilter(eventFilter: m_eventFilter, priority: 512); |
126 | } |
127 | |
128 | void InputHandler::unregisterEventFilters() |
129 | { |
130 | if (m_service) |
131 | m_service->unregisterEventFilter(eventFilter: m_eventFilter); |
132 | } |
133 | |
134 | void InputHandler::setInputSettings(InputSettings *settings) |
135 | { |
136 | if (m_settings && settings == nullptr) { |
137 | unregisterEventFilters(); |
138 | m_lastEventSource = nullptr; |
139 | if (m_settings->eventSource() && m_service) |
140 | m_service->shutdown(eventSource: m_settings->eventSource()); |
141 | } |
142 | if (m_service) { |
143 | unregisterEventFilters(); |
144 | if (m_settings && m_settings->eventSource()) |
145 | m_service->shutdown(eventSource: m_settings->eventSource()); |
146 | } |
147 | m_settings = settings; |
148 | } |
149 | |
150 | void InputHandler::updateEventSource() |
151 | { |
152 | // Called every frame from input aspect |
153 | // Should probably just listen to changes in source property on settings object |
154 | if (!m_settings || !m_service) |
155 | return; |
156 | |
157 | // Will be updated only if eventSource is different than |
158 | // what was set last |
159 | QObject *eventSource = m_settings->eventSource(); |
160 | if (eventSource && m_lastEventSource != eventSource) { |
161 | m_service->initialize(eventSource); |
162 | registerEventFilters(); |
163 | m_lastEventSource = eventSource; |
164 | } |
165 | } |
166 | |
167 | void InputHandler::appendKeyboardDevice(HKeyboardDevice device) |
168 | { |
169 | m_activeKeyboardDevices.append(t: device); |
170 | } |
171 | |
172 | void InputHandler::removeKeyboardDevice(HKeyboardDevice device) |
173 | { |
174 | m_activeKeyboardDevices.removeAll(t: device); |
175 | } |
176 | |
177 | void InputHandler::appendMouseDevice(HMouseDevice device) |
178 | { |
179 | m_activeMouseDevices.append(t: device); |
180 | } |
181 | |
182 | void InputHandler::removeMouseDevice(HMouseDevice device) |
183 | { |
184 | m_activeMouseDevices.removeAll(t: device); |
185 | } |
186 | |
187 | void Qt3DInput::Input::InputHandler::appendGenericDevice(HGenericDeviceBackendNode device) |
188 | { |
189 | m_activeGenericPhysicalDevices.append(t: device); |
190 | } |
191 | |
192 | void Qt3DInput::Input::InputHandler::removeGenericDevice(HGenericDeviceBackendNode device) |
193 | { |
194 | m_activeGenericPhysicalDevices.removeAll(t: device); |
195 | } |
196 | |
197 | // called every frame to reset the |
198 | void Qt3DInput::Input::InputHandler::resetMouseAxisState() |
199 | { |
200 | for (const HMouseDevice &cHandle : std::as_const(t&: m_activeMouseDevices)) { |
201 | MouseDevice *controller = m_mouseDeviceManager->data(handle: cHandle); |
202 | controller->resetMouseAxisState(); |
203 | } |
204 | } |
205 | |
206 | QList<QInputDeviceIntegration *> InputHandler::inputDeviceIntegrations() const |
207 | { |
208 | return m_inputDeviceIntegrations; |
209 | } |
210 | |
211 | void InputHandler::addInputDeviceIntegration(QInputDeviceIntegration *inputIntegration) |
212 | { |
213 | m_inputDeviceIntegrations.push_back(t: inputIntegration); |
214 | } |
215 | |
216 | QAbstractPhysicalDevice *Qt3DInput::Input::InputHandler::createPhysicalDevice(const QString &name) |
217 | { |
218 | QAbstractPhysicalDevice *device = nullptr; |
219 | for (Qt3DInput::QInputDeviceIntegration *integration : std::as_const(t&: m_inputDeviceIntegrations)) { |
220 | if ((device = integration->createPhysicalDevice(name)) != nullptr) |
221 | break; |
222 | } |
223 | return device; |
224 | } |
225 | |
226 | void Qt3DInput::Input::InputHandler::setEventFilterService(QEventFilterService *service) |
227 | { |
228 | m_service = service; |
229 | } |
230 | |
231 | AbstractActionInput *InputHandler::lookupActionInput(Qt3DCore::QNodeId id) const |
232 | { |
233 | AbstractActionInput *input = nullptr; |
234 | if ((input = actionInputManager()->lookupResource(id)) != nullptr) |
235 | return input; |
236 | if ((input = inputSequenceManager()->lookupResource(id)) != nullptr) |
237 | return input; |
238 | return inputChordManager()->lookupResource(id); // nullptr if not found |
239 | } |
240 | |
241 | InternalEventFilter::~InternalEventFilter() = default; |
242 | |
243 | bool InternalEventFilter::processMouseEvent(QObject *obj, QT_PREPEND_NAMESPACE(QMouseEvent) *event) |
244 | { |
245 | Q_UNUSED(obj); |
246 | Q_ASSERT(m_inputHandler); |
247 | if (!m_inputHandler->m_scene) |
248 | return false; |
249 | |
250 | for (const HMouseDevice &cHandle : std::as_const(t&: m_inputHandler->m_activeMouseDevices)) { |
251 | MouseDevice *controller = m_inputHandler->m_mouseDeviceManager->data(handle: cHandle); |
252 | |
253 | controller->updateMouseEvent(events: event); |
254 | |
255 | // Send the events to the mouse handlers that have for sourceDevice controller |
256 | const std::vector<HMouseHandler> &activeMouseHandlers = m_inputHandler->m_mouseInputManager->activeHandles(); |
257 | for (const HMouseHandler &mouseHandlerHandle : activeMouseHandlers) { |
258 | MouseHandler *mouseHandler = m_inputHandler->m_mouseInputManager->data(handle: mouseHandlerHandle); |
259 | Q_ASSERT(mouseHandler); |
260 | |
261 | if (mouseHandler->mouseDevice() == controller->peerId()) { |
262 | QMouseHandler *node = qobject_cast<QMouseHandler *>(object: m_inputHandler->m_scene->lookupNode(id: mouseHandler->peerId())); |
263 | QMouseHandlerPrivate *dnode = static_cast<QMouseHandlerPrivate *>(QMouseHandlerPrivate::get(q: node)); |
264 | dnode->mouseEvent(event: QMouseEventPtr::create(arguments&: *event)); // Do we really need Qt3D specific events? |
265 | } |
266 | } |
267 | } |
268 | |
269 | return false; |
270 | } |
271 | |
272 | #if QT_CONFIG(wheelevent) |
273 | bool InternalEventFilter::processWheelEvent(QObject *obj, QT_PREPEND_NAMESPACE(QWheelEvent) *event) |
274 | { |
275 | Q_UNUSED(obj); |
276 | Q_ASSERT(m_inputHandler); |
277 | if (!m_inputHandler->m_scene) |
278 | return false; |
279 | |
280 | for (const HMouseDevice &cHandle : std::as_const(t&: m_inputHandler->m_activeMouseDevices)) { |
281 | MouseDevice *controller = m_inputHandler->m_mouseDeviceManager->data(handle: cHandle); |
282 | |
283 | controller->updateWheelEvent(events: event); |
284 | |
285 | // Send the events to the mouse handlers that have for sourceDevice controller |
286 | const std::vector<HMouseHandler> &activeMouseHandlers = m_inputHandler->m_mouseInputManager->activeHandles(); |
287 | for (const HMouseHandler &mouseHandlerHandle : activeMouseHandlers) { |
288 | MouseHandler *mouseHandler = m_inputHandler->m_mouseInputManager->data(handle: mouseHandlerHandle); |
289 | Q_ASSERT(mouseHandler); |
290 | |
291 | if (mouseHandler->mouseDevice() == controller->peerId()) { |
292 | QMouseHandler *node = qobject_cast<QMouseHandler *>(object: m_inputHandler->m_scene->lookupNode(id: mouseHandler->peerId())); |
293 | QWheelEvent we(*event); |
294 | node->wheel(wheel: &we); // Do we really need Qt3D specific events? |
295 | } |
296 | } |
297 | } |
298 | |
299 | return false; |
300 | } |
301 | #endif |
302 | |
303 | bool InternalEventFilter::processKeyEvent(QObject *obj, QT_PREPEND_NAMESPACE(QKeyEvent) *event) |
304 | { |
305 | Q_UNUSED(obj); |
306 | Q_ASSERT(m_inputHandler); |
307 | if (!m_inputHandler->m_scene) |
308 | return false; |
309 | |
310 | for (const HKeyboardDevice &cHandle : std::as_const(t&: m_inputHandler->m_activeKeyboardDevices)) { |
311 | KeyboardDevice *keyboardDevice = m_inputHandler->m_keyboardDeviceManager->data(handle: cHandle); |
312 | if (keyboardDevice) { |
313 | keyboardDevice->updateKeyEvent(event); |
314 | |
315 | // update the focus |
316 | if (keyboardDevice->lastKeyboardInputRequester() != keyboardDevice->currentFocusItem()) { |
317 | const auto handles = m_inputHandler->keyboardInputManager()->activeHandles(); |
318 | for (const HKeyboardHandler &handle : handles) { |
319 | KeyboardHandler *input = m_inputHandler->keyboardInputManager()->data(handle); |
320 | Q_ASSERT(input); |
321 | if (input->keyboardDevice() == keyboardDevice->peerId()) { |
322 | bool hasFocus = input->peerId() == keyboardDevice->lastKeyboardInputRequester(); |
323 | input->setFocus(hasFocus); |
324 | QKeyboardHandler *node = qobject_cast<QKeyboardHandler *>(object: m_inputHandler->m_scene->lookupNode(id: input->peerId())); |
325 | if (node) { |
326 | const bool b = node->blockNotifications(block: true); |
327 | node->setFocus(hasFocus); |
328 | node->blockNotifications(block: b); |
329 | } |
330 | if (hasFocus) |
331 | keyboardDevice->setCurrentFocusItem(input->peerId()); |
332 | } |
333 | } |
334 | } |
335 | |
336 | // deliver the event |
337 | QKeyboardHandler *node = qobject_cast<QKeyboardHandler *>(object: m_inputHandler->m_scene->lookupNode(id: keyboardDevice->currentFocusItem())); |
338 | if (node) { |
339 | QKeyboardHandlerPrivate *dnode = static_cast<QKeyboardHandlerPrivate *>(QKeyboardHandlerPrivate::get(q: node)); |
340 | |
341 | QKeyEvent ke(*event); |
342 | dnode->keyEvent(event: &ke); // Do we really need Qt3D specific events? |
343 | } |
344 | } |
345 | } |
346 | |
347 | return false; |
348 | } |
349 | |
350 | |
351 | } // namespace Input |
352 | } // namespace Qt3DInput |
353 | |
354 | QT_END_NAMESPACE |
355 | |