1// Copyright (C) 2019 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 "qquickpointerdevicehandler_p_p.h"
5#include <private/qquickitem_p.h>
6#include <QMouseEvent>
7#include <QDebug>
8
9QT_BEGIN_NAMESPACE
10
11/*!
12 \qmltype PointerDeviceHandler
13 \qmlabstract
14 \since 5.10
15 \preliminary
16 \nativetype QQuickPointerDeviceHandler
17 \inherits PointerHandler
18 \inqmlmodule QtQuick
19 \brief Abstract handler for pointer events with device-specific constraints.
20
21 An intermediate class (not registered as a QML type) for handlers which
22 allow filtering based on device type, pointer type, or keyboard modifiers.
23*/
24QQuickPointerDeviceHandler::QQuickPointerDeviceHandler(QQuickItem *parent)
25 : QQuickPointerHandler(*(new QQuickPointerDeviceHandlerPrivate), parent)
26{
27}
28
29QQuickPointerDeviceHandler::QQuickPointerDeviceHandler(QQuickPointerDeviceHandlerPrivate &dd, QQuickItem *parent)
30 : QQuickPointerHandler(dd, parent)
31{
32}
33
34QInputDevice::DeviceTypes QQuickPointerDeviceHandler::acceptedDevices() const
35{
36 Q_D(const QQuickPointerDeviceHandler);
37 return d->acceptedDevices;
38}
39
40QPointingDevice::PointerTypes QQuickPointerDeviceHandler::acceptedPointerTypes() const
41{
42 Q_D(const QQuickPointerDeviceHandler);
43 return d->acceptedPointerTypes;
44}
45
46/*!
47 \qmlproperty flags QtQuick::PointerDeviceHandler::acceptedButtons
48
49 The mouse buttons which can activate this Pointer Handler.
50
51 By default, this property is set to \l {QtQuick::MouseEvent::button} {Qt.LeftButton}.
52 It can be set to an OR combination of mouse buttons, and will ignore events
53 from other buttons.
54
55 For example, a control could be made to respond to left and right clicks
56 in different ways, with two handlers:
57
58 \qml
59 Item {
60 TapHandler {
61 onTapped: console.log("left clicked")
62 }
63 TapHandler {
64 acceptedButtons: Qt.RightButton
65 onTapped: console.log("right clicked")
66 }
67 }
68 \endqml
69
70 \note Tapping on a touchscreen or tapping the stylus on a graphics tablet
71 emulates clicking the left mouse button. This behavior can be altered via
72 \l {PointerDeviceHandler::acceptedDevices}{acceptedDevices} or
73 \l {PointerDeviceHandler::acceptedPointerTypes}{acceptedPointerTypes}.
74*/
75Qt::MouseButtons QQuickPointerDeviceHandler::acceptedButtons() const
76{
77 Q_D(const QQuickPointerDeviceHandler);
78 return d->acceptedButtons;
79}
80
81void QQuickPointerDeviceHandler::setAcceptedButtons(Qt::MouseButtons buttons)
82{
83 Q_D(QQuickPointerDeviceHandler);
84 if (d->acceptedButtons == buttons)
85 return;
86
87 d->acceptedButtons = buttons;
88 emit acceptedButtonsChanged();
89}
90
91Qt::KeyboardModifiers QQuickPointerDeviceHandler::acceptedModifiers() const
92{
93 Q_D(const QQuickPointerDeviceHandler);
94 return d->acceptedModifiers;
95}
96
97/*!
98 \qmlproperty flags PointerDeviceHandler::acceptedDevices
99
100 The types of pointing devices that can activate this Pointer Handler.
101
102 By default, this property is set to
103 \l{QInputDevice::DeviceType}{PointerDevice.AllDevices}.
104 If you set it to an OR combination of device types, it will ignore events
105 from non-matching devices.
106
107 For example, a control could be made to respond to mouse and stylus clicks
108 in one way, and touchscreen taps in another way, with two handlers:
109
110 \qml
111 Item {
112 TapHandler {
113 acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
114 onTapped: console.log("clicked")
115 }
116 TapHandler {
117 acceptedDevices: PointerDevice.TouchScreen
118 onTapped: console.log("tapped")
119 }
120 }
121 \endqml
122
123 \note Not all platforms are yet able to distinguish mouse and touchpad; and
124 on those that do, you often want to make mouse and touchpad behavior the same.
125*/
126void QQuickPointerDeviceHandler::setAcceptedDevices(QPointingDevice::DeviceTypes acceptedDevices)
127{
128 Q_D(QQuickPointerDeviceHandler);
129 if (d->acceptedDevices == acceptedDevices)
130 return;
131
132 d->acceptedDevices = acceptedDevices;
133 emit acceptedDevicesChanged();
134}
135
136/*!
137 \qmlproperty flags PointerDeviceHandler::acceptedPointerTypes
138
139 The types of pointing instruments (finger, stylus, eraser, etc.)
140 that can activate this Pointer Handler.
141
142 By default, this property is set to
143 \l {QPointingDevice::PointerType} {PointerDevice.AllPointerTypes}.
144 If you set it to an OR combination of device types, it will ignore events
145 from non-matching \l {PointerDevice}{devices}.
146
147 For example, a control could be made to respond to mouse, touch, and stylus clicks
148 in some way, but delete itself if tapped with an eraser tool on a graphics tablet,
149 with two handlers:
150
151 \qml
152 Rectangle {
153 id: rect
154 TapHandler {
155 acceptedPointerTypes: PointerDevice.Generic | PointerDevice.Finger | PointerDevice.Pen
156 onTapped: console.log("clicked")
157 }
158 TapHandler {
159 acceptedPointerTypes: PointerDevice.Eraser
160 onTapped: rect.destroy()
161 }
162 }
163 \endqml
164*/
165void QQuickPointerDeviceHandler::setAcceptedPointerTypes(QPointingDevice::PointerTypes acceptedPointerTypes)
166{
167 Q_D(QQuickPointerDeviceHandler);
168 if (d->acceptedPointerTypes == acceptedPointerTypes)
169 return;
170
171 d->acceptedPointerTypes = acceptedPointerTypes;
172 emit acceptedPointerTypesChanged();
173}
174
175/*!
176 \qmlproperty flags PointerDeviceHandler::acceptedModifiers
177
178 If this property is set, it will require the given keyboard modifiers to
179 be pressed in order to react to pointer events, and otherwise ignore them.
180
181 If this property is set to \c Qt.KeyboardModifierMask (the default value),
182 then the PointerHandler ignores the modifier keys.
183
184 For example, an \l [QML] Item could have two handlers of the same type,
185 one of which is enabled only if the required keyboard modifiers are
186 pressed:
187
188 \qml
189 Item {
190 TapHandler {
191 acceptedModifiers: Qt.ControlModifier
192 onTapped: console.log("control-tapped")
193 }
194 TapHandler {
195 acceptedModifiers: Qt.NoModifier
196 onTapped: console.log("tapped")
197 }
198 }
199 \endqml
200
201 If you set \c acceptedModifiers to an OR combination of modifier keys,
202 it means \e all of those modifiers must be pressed to activate the handler:
203
204 \qml
205 Item {
206 TapHandler {
207 acceptedModifiers: Qt.ControlModifier | Qt.AltModifier | Qt.ShiftModifier
208 onTapped: console.log("control-alt-shift-tapped")
209 }
210 }
211 \endqml
212
213 The available modifiers are as follows:
214
215 \value NoModifier No modifier key is allowed.
216 \value ShiftModifier A Shift key on the keyboard must be pressed.
217 \value ControlModifier A Ctrl key on the keyboard must be pressed.
218 \value AltModifier An Alt key on the keyboard must be pressed.
219 \value MetaModifier A Meta key on the keyboard must be pressed.
220 \value KeypadModifier A keypad button must be pressed.
221 \value GroupSwitchModifier X11 only (unless activated on Windows by a command line argument).
222 A Mode_switch key on the keyboard must be pressed.
223 \value KeyboardModifierMask The handler does not care which modifiers are pressed.
224
225 If you need even more complex behavior than can be achieved with
226 combinations of multiple handlers with multiple modifier flags, you can
227 check the modifiers in JavaScript code:
228
229 \qml
230 Item {
231 TapHandler {
232 onTapped:
233 switch (point.modifiers) {
234 case Qt.ControlModifier | Qt.AltModifier:
235 console.log("CTRL+ALT");
236 break;
237 case Qt.ControlModifier | Qt.AltModifier | Qt.MetaModifier:
238 console.log("CTRL+META+ALT");
239 break;
240 default:
241 console.log("other modifiers", point.modifiers);
242 break;
243 }
244 }
245 }
246 \endqml
247
248 \sa Qt::KeyboardModifier
249*/
250void QQuickPointerDeviceHandler::setAcceptedModifiers(Qt::KeyboardModifiers acceptedModifiers)
251{
252 Q_D(QQuickPointerDeviceHandler);
253 if (d->acceptedModifiers == acceptedModifiers)
254 return;
255
256 d->acceptedModifiers = acceptedModifiers;
257 emit acceptedModifiersChanged();
258}
259
260bool QQuickPointerDeviceHandler::wantsPointerEvent(QPointerEvent *event)
261{
262 Q_D(QQuickPointerDeviceHandler);
263 if (!QQuickPointerHandler::wantsPointerEvent(event))
264 return false;
265 qCDebug(lcPointerHandlerDispatch) << objectName()
266 << "checking device type" << d->acceptedDevices
267 << "pointer type" << d->acceptedPointerTypes
268 << "modifiers" << d->acceptedModifiers;
269 if (!d->acceptedDevices.testFlag(flag: event->device()->type()))
270 return false;
271 if (!d->acceptedPointerTypes.testFlag(flag: event->pointingDevice()->pointerType()))
272 return false;
273 if (d->acceptedModifiers != Qt::KeyboardModifierMask && event->modifiers() != d->acceptedModifiers)
274 return false;
275 // Some handlers (HoverHandler, PinchHandler, PointHandler) set
276 // acceptedButtons to Qt::NoButton to indicate that button state is irrelevant.
277 if (event->isSinglePointEvent() && acceptedButtons() != Qt::NoButton && event->type() != QEvent::Wheel &&
278 (static_cast<QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == 0 &&
279 (static_cast<QSinglePointEvent *>(event)->button() & acceptedButtons()) == 0)
280 return false;
281 return true;
282}
283
284QT_END_NAMESPACE
285
286#include "moc_qquickpointerdevicehandler_p.cpp"
287

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/quick/handlers/qquickpointerdevicehandler.cpp