1/****************************************************************************
2**
3** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "inputhandler_p.h"
41
42#include <Qt3DInput/private/assignkeyboardfocusjob_p.h>
43#include <Qt3DInput/private/eventsourcesetterhelper_p.h>
44#include <Qt3DInput/private/inputmanagers_p.h>
45#include <Qt3DInput/private/inputsettings_p.h>
46#include <Qt3DInput/private/keyboardeventfilter_p.h>
47#include <Qt3DInput/private/keyeventdispatcherjob_p.h>
48#include <Qt3DInput/private/mouseeventdispatcherjob_p.h>
49#include <Qt3DInput/private/mouseeventfilter_p.h>
50#include <Qt3DInput/private/qinputdeviceintegration_p.h>
51#include <Qt3DCore/private/qeventfilterservice_p.h>
52
53QT_BEGIN_NAMESPACE
54
55using namespace Qt3DCore;
56
57namespace Qt3DInput {
58namespace Input {
59
60InputHandler::InputHandler()
61 : m_keyboardDeviceManager(new KeyboardDeviceManager())
62 , m_keyboardInputManager(new KeyboardInputManager())
63 , m_mouseDeviceManager(new MouseDeviceManager())
64 , m_mouseInputManager(new MouseInputManager())
65 , m_keyboardEventFilter(new KeyboardEventFilter())
66 , m_mouseEventFilter(new MouseEventFilter())
67 , m_axisManager(new AxisManager())
68 , m_axisAccumulatorManager(new AxisAccumulatorManager())
69 , m_actionManager(new ActionManager())
70 , m_axisSettingManager(new AxisSettingManager())
71 , m_actionInputManager(new ActionInputManager())
72 , m_analogAxisInputManager(new AnalogAxisInputManager())
73 , m_buttonAxisInputManager(new ButtonAxisInputManager())
74 , m_inputChordManager(new InputChordManager())
75 , m_inputSequenceManager(new InputSequenceManager())
76 , m_logicalDeviceManager(new LogicalDeviceManager())
77 , m_genericPhysicalDeviceBackendNodeManager(new GenericDeviceBackendNodeManager)
78 , m_physicalDeviceProxyManager(new PhysicalDeviceProxyManager())
79 , m_settings(nullptr)
80 , m_eventSourceSetter(new Qt3DInput::Input::EventSourceSetterHelper(this))
81{
82 m_keyboardEventFilter->setInputHandler(this);
83 m_mouseEventFilter->setInputHandler(this);
84
85 // Created in the main thread
86 // m_eventSourceSetter needs to be in the main thread
87}
88
89InputHandler::~InputHandler()
90{
91 delete m_keyboardDeviceManager;
92 delete m_keyboardInputManager;
93 delete m_mouseDeviceManager;
94 delete m_mouseInputManager;
95 delete m_keyboardEventFilter;
96 delete m_mouseEventFilter;
97 delete m_axisManager;
98 delete m_axisAccumulatorManager;
99 delete m_actionManager;
100 delete m_axisSettingManager;
101 delete m_analogAxisInputManager;
102 delete m_buttonAxisInputManager;
103 delete m_actionInputManager;
104 delete m_inputChordManager;
105 delete m_inputSequenceManager;
106 delete m_logicalDeviceManager;
107 delete m_genericPhysicalDeviceBackendNodeManager;
108 delete m_physicalDeviceProxyManager;
109}
110
111// Called in MainThread (by the EventSourceHelperSetter)
112void InputHandler::registerEventFilters(QEventFilterService *service)
113{
114 clearPendingKeyEvents();
115 clearPendingMouseEvents();
116
117 service->registerEventFilter(eventFilter: m_keyboardEventFilter, priority: 512);
118 service->registerEventFilter(eventFilter: m_mouseEventFilter, priority: 513);
119}
120
121void InputHandler::unregisterEventFilters(Qt3DCore::QEventFilterService *service)
122{
123 service->unregisterEventFilter(eventFilter: m_keyboardEventFilter);
124 service->unregisterEventFilter(eventFilter: m_mouseEventFilter);
125}
126
127// Called by the keyboardEventFilter in the main thread
128void InputHandler::appendKeyEvent(const QT_PREPEND_NAMESPACE(QKeyEvent) &event)
129{
130 m_pendingKeyEvents.append(t: event);
131}
132
133// Called by QInputASpect::jobsToExecute (Main Thread)
134QList<QT_PREPEND_NAMESPACE(QKeyEvent)> InputHandler::pendingKeyEvents()
135{
136 return std::move(m_pendingKeyEvents);
137}
138
139// Called by QInputASpect::jobsToExecute (Main Thread)
140void InputHandler::clearPendingKeyEvents()
141{
142 m_pendingKeyEvents.clear();
143}
144
145// Main Thread
146void InputHandler::appendMouseEvent(const QT_PREPEND_NAMESPACE(QMouseEvent) &event)
147{
148 m_pendingMouseEvents.append(t: event);
149}
150
151// Main Thread
152QList<QT_PREPEND_NAMESPACE(QMouseEvent)> InputHandler::pendingMouseEvents()
153{
154 return std::move(m_pendingMouseEvents);
155}
156
157// Main Thread
158void InputHandler::clearPendingMouseEvents()
159{
160 m_pendingMouseEvents.clear();
161}
162
163#if QT_CONFIG(wheelevent)
164// Main Thread
165void InputHandler::appendWheelEvent(const QT_PREPEND_NAMESPACE(QWheelEvent) &event)
166{
167 m_pendingWheelEvents.append(t: event);
168}
169
170// Main Thread
171QList<QT_PREPEND_NAMESPACE (QWheelEvent)> Qt3DInput::Input::InputHandler::pendingWheelEvents()
172{
173 return std::move(m_pendingWheelEvents);
174}
175
176// Main Thread
177void InputHandler::clearPendingWheelEvents()
178{
179 m_pendingWheelEvents.clear();
180}
181#endif
182
183void InputHandler::appendKeyboardDevice(HKeyboardDevice device)
184{
185 m_activeKeyboardDevices.append(t: device);
186}
187
188void InputHandler::removeKeyboardDevice(HKeyboardDevice device)
189{
190 m_activeKeyboardDevices.removeAll(t: device);
191}
192
193void InputHandler::appendMouseDevice(HMouseDevice device)
194{
195 m_activeMouseDevices.append(t: device);
196}
197
198void InputHandler::removeMouseDevice(HMouseDevice device)
199{
200 m_activeMouseDevices.removeAll(t: device);
201}
202
203void Qt3DInput::Input::InputHandler::appendGenericDevice(HGenericDeviceBackendNode device)
204{
205 m_activeGenericPhysicalDevices.append(t: device);
206}
207
208void Qt3DInput::Input::InputHandler::removeGenericDevice(HGenericDeviceBackendNode device)
209{
210 m_activeGenericPhysicalDevices.removeAll(t: device);
211}
212
213// Return a vector of jobs to be performed for keyboard events
214// Handles all dependencies between jobs
215QVector<Qt3DCore::QAspectJobPtr> InputHandler::keyboardJobs()
216{
217 // One job for Keyboard focus change event per Keyboard device
218 QVector<QAspectJobPtr> jobs;
219 const QList<QT_PREPEND_NAMESPACE(QKeyEvent)> events = pendingKeyEvents();
220
221 for (const HKeyboardDevice &cHandle : qAsConst(t&: m_activeKeyboardDevices)) {
222 KeyboardDevice *keyboardDevice = m_keyboardDeviceManager->data(handle: cHandle);
223 if (keyboardDevice) {
224 keyboardDevice->updateKeyEvents(events);
225 bool haveFocusChangeJob = false;
226 if (keyboardDevice->lastKeyboardInputRequester() != keyboardDevice->currentFocusItem()) {
227 auto job = QSharedPointer<AssignKeyboardFocusJob>::create(arguments: keyboardDevice->peerId());
228 job->setInputHandler(this);
229 haveFocusChangeJob= true;
230 jobs.append(t: std::move(job));
231 // One job for Keyboard events (depends on the focus change job if there was one)
232 }
233 // Event dispacthing job
234 if (!events.isEmpty()) {
235 auto job = QSharedPointer<KeyEventDispatcherJob>::create(arguments: keyboardDevice->currentFocusItem(), arguments: events);
236 job->setInputHandler(this);
237 if (haveFocusChangeJob)
238 job->addDependency(dependency: qAsConst(t&: jobs).back());
239 jobs.append(t: std::move(job));
240 }
241 }
242 }
243 return jobs;
244}
245
246QVector<Qt3DCore::QAspectJobPtr> InputHandler::mouseJobs()
247{
248 QVector<QAspectJobPtr> jobs;
249 const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> mouseEvents = pendingMouseEvents();
250#if QT_CONFIG(wheelevent)
251 const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> wheelEvents = pendingWheelEvents();
252#endif
253 for (const HMouseDevice &cHandle : qAsConst(t&: m_activeMouseDevices)) {
254 MouseDevice *controller = m_mouseDeviceManager->data(handle: cHandle);
255
256 controller->updateMouseEvents(events: mouseEvents);
257#if QT_CONFIG(wheelevent)
258 controller->updateWheelEvents(events: wheelEvents);
259#endif
260 // Event dispacthing job
261 if (!mouseEvents.isEmpty()
262#if QT_CONFIG(wheelevent)
263 || !wheelEvents.empty()
264#endif
265 ) {
266 // Send the events to the mouse handlers that have for sourceDevice controller
267 const std::vector<HMouseHandler> &activeMouseHandlers = m_mouseInputManager->activeHandles();
268 for (const HMouseHandler &mouseHandlerHandle : activeMouseHandlers) {
269
270 MouseHandler *mouseHandler = m_mouseInputManager->data(handle: mouseHandlerHandle);
271 Q_ASSERT(mouseHandler);
272
273 if (mouseHandler->mouseDevice() == controller->peerId()) {
274 MouseEventDispatcherJob *job = new MouseEventDispatcherJob(mouseHandler->peerId(),
275 mouseEvents
276#if QT_CONFIG(wheelevent)
277 , wheelEvents
278#endif
279 );
280 job->setInputHandler(this);
281 jobs.append(t: QAspectJobPtr(job));
282 }
283 }
284 }
285 }
286
287 return jobs;
288}
289
290QVector<QInputDeviceIntegration *> InputHandler::inputDeviceIntegrations() const
291{
292 return m_inputDeviceIntegrations;
293}
294
295void InputHandler::addInputDeviceIntegration(QInputDeviceIntegration *inputIntegration)
296{
297 m_inputDeviceIntegrations.push_back(t: inputIntegration);
298}
299
300void InputHandler::setInputSettings(InputSettings *settings)
301{
302 if (m_settings && settings == nullptr)
303 m_eventSourceSetter->unsetEventSource(eventSource: m_settings->eventSource());
304 m_settings = settings;
305}
306
307void InputHandler::setEventSourceHelper(EventSourceSetterHelper *helper)
308{
309 m_eventSourceSetter.reset(other: helper);
310}
311
312EventSourceSetterHelper *InputHandler::eventSourceHelper() const
313{
314 return m_eventSourceSetter.data();
315}
316
317QAbstractPhysicalDevice *Qt3DInput::Input::InputHandler::createPhysicalDevice(const QString &name)
318{
319 QAbstractPhysicalDevice *device = nullptr;
320 for (Qt3DInput::QInputDeviceIntegration *integration : qAsConst(t&: m_inputDeviceIntegrations)) {
321 if ((device = integration->createPhysicalDevice(name)) != nullptr)
322 break;
323 }
324 return device;
325}
326
327void InputHandler::updateEventSource()
328{
329 if (m_settings != nullptr) {
330 // Will be updated only if eventSource is different than
331 // what was set last
332 QObject *eventSource = m_settings->eventSource();
333 m_eventSourceSetter->setEventSource(eventSource);
334 }
335}
336
337AbstractActionInput *InputHandler::lookupActionInput(Qt3DCore::QNodeId id) const
338{
339 AbstractActionInput *input = nullptr;
340 if ((input = actionInputManager()->lookupResource(id)) != nullptr)
341 return input;
342 if ((input = inputSequenceManager()->lookupResource(id)) != nullptr)
343 return input;
344 return inputChordManager()->lookupResource(id); // nullptr if not found
345}
346
347} // namespace Input
348} // namespace Qt3DInput
349
350QT_END_NAMESPACE
351

source code of qt3d/src/input/backend/inputhandler.cpp