1 | // Copyright (C) 2020 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 "qquickevents_p_p.h" |
5 | #include <QtCore/qmap.h> |
6 | #include <QtGui/private/qguiapplication_p.h> |
7 | #include <QtGui/private/qinputdevice_p.h> |
8 | #include <QtGui/private/qevent_p.h> |
9 | #include <QtQuick/private/qquickitem_p.h> |
10 | #include <QtQuick/private/qquickpointerhandler_p.h> |
11 | #include <QtQuick/private/qquickpointerhandler_p_p.h> |
12 | #include <QtQuick/private/qquickwindow_p.h> |
13 | #include <private/qdebug_p.h> |
14 | |
15 | QT_BEGIN_NAMESPACE |
16 | |
17 | Q_LOGGING_CATEGORY(lcPointerEvents, "qt.quick.pointer.events" ) |
18 | |
19 | /*! |
20 | \qmltype KeyEvent |
21 | \instantiates QQuickKeyEvent |
22 | \inqmlmodule QtQuick |
23 | \ingroup qtquick-input-events |
24 | |
25 | \brief Provides information about a key event. |
26 | |
27 | For example, the following changes the Item's state property when the Enter |
28 | key is pressed: |
29 | \qml |
30 | Item { |
31 | focus: true |
32 | Keys.onPressed: (event)=> { if (event.key == Qt.Key_Enter) state = 'ShowDetails'; } |
33 | } |
34 | \endqml |
35 | */ |
36 | |
37 | /*! |
38 | \qmlproperty int QtQuick::KeyEvent::key |
39 | |
40 | This property holds the code of the key that was pressed or released. |
41 | |
42 | See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are |
43 | independent of the underlying window system. Note that this |
44 | function does not distinguish between capital and non-capital |
45 | letters; use the \l {KeyEvent::}{text} property for this purpose. |
46 | |
47 | A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not |
48 | the result of a known key; for example, it may be the result of |
49 | a compose sequence, a keyboard macro, or due to key event |
50 | compression. |
51 | */ |
52 | |
53 | /*! |
54 | \qmlproperty string QtQuick::KeyEvent::text |
55 | |
56 | This property holds the Unicode text that the key generated. |
57 | The text returned can be an empty string in cases where modifier keys, |
58 | such as Shift, Control, Alt, and Meta, are being pressed or released. |
59 | In such cases \c key will contain a valid value |
60 | */ |
61 | |
62 | /*! |
63 | \qmlproperty bool QtQuick::KeyEvent::isAutoRepeat |
64 | |
65 | This property holds whether this event comes from an auto-repeating key. |
66 | */ |
67 | |
68 | /*! |
69 | \qmlproperty quint32 QtQuick::KeyEvent::nativeScanCode |
70 | |
71 | This property contains the native scan code of the key that was pressed. It is |
72 | passed through from QKeyEvent unchanged. |
73 | |
74 | \sa QKeyEvent::nativeScanCode() |
75 | */ |
76 | |
77 | /*! |
78 | \qmlproperty int QtQuick::KeyEvent::count |
79 | |
80 | This property holds the number of keys involved in this event. If \l KeyEvent::text |
81 | is not empty, this is simply the length of the string. |
82 | */ |
83 | |
84 | /*! |
85 | \qmlproperty bool QtQuick::KeyEvent::accepted |
86 | |
87 | Setting \a accepted to true prevents the key event from being |
88 | propagated to the item's parent. |
89 | |
90 | Generally, if the item acts on the key event then it should be accepted |
91 | so that ancestor items do not also respond to the same event. |
92 | */ |
93 | |
94 | /*! |
95 | \qmlproperty int QtQuick::KeyEvent::modifiers |
96 | |
97 | This property holds the keyboard modifier flags that existed immediately |
98 | before the event occurred. |
99 | |
100 | It contains a bitwise combination of numeric values (the same as in Qt::KeyboardModifier): |
101 | |
102 | \value Qt.NoModifier No modifier key is pressed. |
103 | \value Qt.ShiftModifier} A Shift key on the keyboard is pressed. |
104 | \value Qt.ControlModifier A Ctrl key on the keyboard is pressed. |
105 | \value Qt.AltModifier An Alt key on the keyboard is pressed. |
106 | \value Qt.MetaModifier A Meta key on the keyboard is pressed. |
107 | \value Qt.KeypadModifier A keypad button is pressed. |
108 | \value Qt.GroupSwitchModifier X11 only. A Mode_switch key on the keyboard is pressed. |
109 | |
110 | For example, to react to a Shift key + Enter key combination: |
111 | \qml |
112 | Item { |
113 | focus: true |
114 | Keys.onPressed: (event)=> { |
115 | if ((event.key == Qt.Key_Enter) && (event.modifiers & Qt.ShiftModifier)) |
116 | doSomething(); |
117 | } |
118 | } |
119 | \endqml |
120 | */ |
121 | |
122 | /*! |
123 | \qmlmethod bool QtQuick::KeyEvent::matches(StandardKey matchKey) |
124 | \since 5.2 |
125 | |
126 | Returns \c true if the key event matches the given standard \a matchKey; otherwise returns \c false. |
127 | |
128 | \qml |
129 | Item { |
130 | focus: true |
131 | Keys.onPressed: (event)=> { |
132 | if (event.matches(StandardKey.Undo)) |
133 | myModel.undo(); |
134 | else if (event.matches(StandardKey.Redo)) |
135 | myModel.redo(); |
136 | } |
137 | } |
138 | \endqml |
139 | |
140 | \sa QKeySequence::StandardKey |
141 | */ |
142 | #if QT_CONFIG(shortcut) |
143 | bool QQuickKeyEvent::matches(QKeySequence::StandardKey matchKey) const |
144 | { |
145 | // copying QKeyEvent::matches |
146 | uint searchkey = (modifiers() | key()) & ~(Qt::KeypadModifier | Qt::GroupSwitchModifier); |
147 | |
148 | const QList<QKeySequence> bindings = QKeySequence::keyBindings(key: matchKey); |
149 | return bindings.contains(t: QKeySequence(searchkey)); |
150 | } |
151 | #endif |
152 | |
153 | |
154 | /*! |
155 | \qmltype MouseEvent |
156 | \instantiates QQuickMouseEvent |
157 | \inqmlmodule QtQuick |
158 | \ingroup qtquick-input-events |
159 | |
160 | \brief Provides information about a mouse event. |
161 | |
162 | The position of the mouse can be found via the \l {Item::x} {x} and \l {Item::y} {y} properties. |
163 | The button that caused the event is available via the \l button property. |
164 | |
165 | \sa MouseArea |
166 | */ |
167 | |
168 | /*! |
169 | \internal |
170 | \class QQuickMouseEvent |
171 | */ |
172 | |
173 | /*! |
174 | \qmlproperty real QtQuick::MouseEvent::x |
175 | \qmlproperty real QtQuick::MouseEvent::y |
176 | |
177 | These properties hold the coordinates of the position supplied by the mouse event. |
178 | */ |
179 | |
180 | |
181 | /*! |
182 | \qmlproperty bool QtQuick::MouseEvent::accepted |
183 | |
184 | Setting \a accepted to true prevents the mouse event from being |
185 | propagated to items below this item. |
186 | |
187 | Generally, if the item acts on the mouse event then it should be accepted |
188 | so that items lower in the stacking order do not also respond to the same event. |
189 | */ |
190 | |
191 | /*! |
192 | \qmlproperty enumeration QtQuick::MouseEvent::button |
193 | |
194 | This property holds the button that caused the event. It can be one of: |
195 | \list |
196 | \li \l {Qt::LeftButton} {Qt.LeftButton} |
197 | \li \l {Qt::RightButton} {Qt.RightButton} |
198 | \li \l {Qt::MiddleButton} {Qt.MiddleButton} |
199 | \endlist |
200 | */ |
201 | |
202 | /*! |
203 | \qmlproperty bool QtQuick::MouseEvent::wasHeld |
204 | |
205 | This property is true if the mouse button has been held pressed longer |
206 | than the threshold (800ms). |
207 | */ |
208 | |
209 | /*! |
210 | \qmlproperty int QtQuick::MouseEvent::buttons |
211 | |
212 | This property holds the mouse buttons pressed when the event was generated. |
213 | For mouse move events, this is all buttons that are pressed down. For mouse |
214 | press and double click events this includes the button that caused the event. |
215 | For mouse release events this excludes the button that caused the event. |
216 | |
217 | It contains a bitwise combination of: |
218 | \list |
219 | \li \l {Qt::LeftButton} {Qt.LeftButton} |
220 | \li \l {Qt::RightButton} {Qt.RightButton} |
221 | \li \l {Qt::MiddleButton} {Qt.MiddleButton} |
222 | \endlist |
223 | */ |
224 | |
225 | /*! |
226 | \qmlproperty int QtQuick::MouseEvent::modifiers |
227 | |
228 | This property holds the keyboard modifier flags that existed immediately |
229 | before the event occurred. |
230 | |
231 | It contains a bitwise combination of: |
232 | \list |
233 | \li \l {Qt::NoModifier} {Qt.NoModifier} - No modifier key is pressed. |
234 | \li \l {Qt::ShiftModifier} {Qt.ShiftModifier} - A Shift key on the keyboard is pressed. |
235 | \li \l {Qt::ControlModifier} {Qt.ControlModifier} - A Ctrl key on the keyboard is pressed. |
236 | \li \l {Qt::AltModifier} {Qt.AltModifier} - An Alt key on the keyboard is pressed. |
237 | \li \l {Qt::MetaModifier} {Qt.MetaModifier} - A Meta key on the keyboard is pressed. |
238 | \li \l {Qt::KeypadModifier} {Qt.KeypadModifier} - A keypad button is pressed. |
239 | \endlist |
240 | |
241 | For example, to react to a Shift key + Left mouse button click: |
242 | \qml |
243 | MouseArea { |
244 | onClicked: (mouse)=> { |
245 | if ((mouse.button == Qt.LeftButton) && (mouse.modifiers & Qt.ShiftModifier)) |
246 | doSomething(); |
247 | } |
248 | } |
249 | \endqml |
250 | */ |
251 | |
252 | /*! |
253 | \qmlproperty int QtQuick::MouseEvent::source |
254 | \since 5.7 |
255 | \deprecated [6.2] Use \l {Qt Quick Input Handlers}{input handlers} with \l {PointerDeviceHandler::acceptedDevices}{acceptedDevices} set. |
256 | |
257 | This property holds the source of the mouse event. |
258 | |
259 | The mouse event source can be used to distinguish between genuine and |
260 | artificial mouse events. When using other pointing devices such as |
261 | touchscreens and graphics tablets, if the application does not make use of |
262 | the actual touch or tablet events, mouse events may be synthesized by the |
263 | operating system or by Qt itself. |
264 | |
265 | The value can be one of: |
266 | |
267 | \list |
268 | \li \l{Qt::MouseEventNotSynthesized} {Qt.MouseEventNotSynthesized} |
269 | - The most common value. On platforms where such information is |
270 | available, this value indicates that the event represents a genuine |
271 | mouse event from the system. |
272 | |
273 | \li \l{Qt::MouseEventSynthesizedBySystem} {Qt.MouseEventSynthesizedBySystem} - Indicates that the mouse event was |
274 | synthesized from a touch or tablet event by the platform. |
275 | |
276 | \li \l{Qt::MouseEventSynthesizedByQt} {Qt.MouseEventSynthesizedByQt} |
277 | - Indicates that the mouse event was synthesized from an unhandled |
278 | touch or tablet event by Qt. |
279 | |
280 | \li \l{Qt::MouseEventSynthesizedByApplication} {Qt.MouseEventSynthesizedByApplication} |
281 | - Indicates that the mouse event was synthesized by the application. |
282 | This allows distinguishing application-generated mouse events from |
283 | the ones that are coming from the system or are synthesized by Qt. |
284 | \endlist |
285 | |
286 | For example, to react only to events which come from an actual mouse: |
287 | \qml |
288 | MouseArea { |
289 | onPressed: (mouse)=> { |
290 | if (mouse.source !== Qt.MouseEventNotSynthesized) |
291 | mouse.accepted = false |
292 | } |
293 | |
294 | onClicked: doSomething() |
295 | } |
296 | \endqml |
297 | |
298 | If the handler for the press event rejects the event, it will be propagated |
299 | further, and then another Item underneath can handle synthesized events |
300 | from touchscreens. For example, if a Flickable is used underneath (and the |
301 | MouseArea is not a child of the Flickable), it can be useful for the |
302 | MouseArea to handle genuine mouse events in one way, while allowing touch |
303 | events to fall through to the Flickable underneath, so that the ability to |
304 | flick on a touchscreen is retained. In that case the ability to drag the |
305 | Flickable via mouse would be lost, but it does not prevent Flickable from |
306 | receiving mouse wheel events. |
307 | */ |
308 | |
309 | /*! |
310 | \qmlproperty int QtQuick::MouseEvent::flags |
311 | \since 5.11 |
312 | |
313 | This property holds the flags that provide additional information about the |
314 | mouse event. |
315 | |
316 | \list |
317 | \li \l {Qt::MouseEventCreatedDoubleClick} {Qt.MouseEventCreatedDoubleClick} |
318 | - Indicates that Qt has created a double click event from this event. |
319 | This flag is set in the event originating from a button press, and not |
320 | in the resulting double click event. |
321 | \endlist |
322 | */ |
323 | |
324 | /*! |
325 | \qmltype WheelEvent |
326 | \instantiates QQuickWheelEvent |
327 | \inqmlmodule QtQuick |
328 | \ingroup qtquick-input-events |
329 | \brief Provides information about a mouse wheel event. |
330 | |
331 | The position of the mouse can be found via the \l x and \l y properties. |
332 | |
333 | \sa WheelHandler, MouseArea |
334 | */ |
335 | |
336 | /*! |
337 | \internal |
338 | \class QQuickWheelEvent |
339 | */ |
340 | |
341 | /*! |
342 | \qmlproperty real QtQuick::WheelEvent::x |
343 | \qmlproperty real QtQuick::WheelEvent::y |
344 | |
345 | These properties hold the coordinates of the position supplied by the wheel event. |
346 | |
347 | \sa QWheelEvent::position() |
348 | */ |
349 | |
350 | /*! |
351 | \qmlproperty bool QtQuick::WheelEvent::accepted |
352 | |
353 | Setting \a accepted to \c true prevents the wheel event from being |
354 | propagated to items below the receiving item or handler. |
355 | |
356 | Generally, if the item acts on the wheel event, it should be accepted |
357 | so that items lower in the stacking order do not also respond to the same event. |
358 | |
359 | \sa QWheelEvent::accepted |
360 | */ |
361 | |
362 | /*! |
363 | \qmlproperty int QtQuick::WheelEvent::buttons |
364 | |
365 | This property holds the mouse buttons pressed when the wheel event was generated. |
366 | |
367 | It contains a bitwise combination of: |
368 | \list |
369 | \li \l {Qt::LeftButton} {Qt.LeftButton} |
370 | \li \l {Qt::RightButton} {Qt.RightButton} |
371 | \li \l {Qt::MiddleButton} {Qt.MiddleButton} |
372 | \endlist |
373 | |
374 | \sa QWheelEvent::buttons() |
375 | */ |
376 | |
377 | /*! |
378 | \qmlproperty point QtQuick::WheelEvent::angleDelta |
379 | |
380 | This property holds the relative amount that the wheel was rotated, in |
381 | eighths of a degree. The \c x and \c y coordinates of this property hold |
382 | the delta in horizontal and vertical orientations, respectively. |
383 | |
384 | A positive value indicates that the wheel was rotated up/right; |
385 | a negative value indicates that the wheel was rotated down/left. |
386 | |
387 | Most mouse types work in steps of \c 15 degrees, in which case the delta value is a |
388 | multiple of \c 120; i.e., \c {120 units * 1/8 = 15 degrees}. |
389 | |
390 | \sa QWheelEvent::angleDelta() |
391 | */ |
392 | |
393 | /*! |
394 | \qmlproperty point QtQuick::WheelEvent::pixelDelta |
395 | |
396 | This property holds the delta in screen pixels and is available in platforms that |
397 | have high-resolution \l {QInputDevice::DeviceType::TouchPad}{trackpads}, such as \macos. |
398 | The \c x and \c y coordinates of this property hold the delta in horizontal |
399 | and vertical orientations, respectively. The values can be used directly to |
400 | scroll content on screen. |
401 | |
402 | For platforms without \l {QInputDevice::Capability::PixelScroll}{high-resolution trackpad} |
403 | support, pixelDelta will always be \c {(0,0)}, and \l angleDelta should be used instead. |
404 | |
405 | \sa QWheelEvent::pixelDelta() |
406 | */ |
407 | |
408 | /*! |
409 | \qmlproperty int QtQuick::WheelEvent::modifiers |
410 | |
411 | This property holds the keyboard modifier flags that existed immediately |
412 | before the event occurred. |
413 | |
414 | It contains a bitwise combination of: |
415 | \list |
416 | \li \l {Qt::NoModifier} {Qt.NoModifier} - No modifier key is pressed. |
417 | \li \l {Qt::ShiftModifier} {Qt.ShiftModifier} - A Shift key on the keyboard is pressed. |
418 | \li \l {Qt::ControlModifier} {Qt.ControlModifier} - A Ctrl key on the keyboard is pressed. |
419 | \li \l {Qt::AltModifier} {Qt.AltModifier} - An Alt key on the keyboard is pressed. |
420 | \li \l {Qt::MetaModifier} {Qt.MetaModifier} - A Meta key on the keyboard is pressed. |
421 | \li \l {Qt::KeypadModifier} {Qt.KeypadModifier} - A keypad button is pressed. |
422 | \endlist |
423 | |
424 | For example, to react to a Control key pressed during the wheel event: |
425 | \qml |
426 | WheelHandler { |
427 | onWheel: (wheel)=> { |
428 | if (wheel.modifiers & Qt.ControlModifier) { |
429 | adjustZoom(wheel.angleDelta.y / 120); |
430 | } |
431 | } |
432 | } |
433 | \endqml |
434 | |
435 | \sa QWheelEvent::modifiers() |
436 | */ |
437 | |
438 | /*! |
439 | \qmlproperty bool QtQuick::WheelEvent::inverted |
440 | |
441 | Returns whether the delta values delivered with the event are inverted. |
442 | |
443 | Normally, a vertical wheel will produce a WheelEvent with positive delta |
444 | values if the top of the wheel is rotating away from the hand operating it. |
445 | Similarly, a horizontal wheel movement will produce a QWheelEvent with |
446 | positive delta values if the top of the wheel is moved to the left. |
447 | |
448 | However, on some platforms this is configurable, so that the same |
449 | operations described above will produce negative delta values (but with the |
450 | same magnitude). For instance, in a QML component (such as a tumbler or a |
451 | slider) where it is appropriate to synchronize the movement or rotation of |
452 | an item with the direction of the wheel, regardless of the system settings, |
453 | the wheel event handler can use the inverted property to decide whether to |
454 | negate the angleDelta or pixelDelta values. |
455 | |
456 | \note Many platforms provide no such information. On such platforms |
457 | \c inverted always returns \c false. |
458 | |
459 | \sa QWheelEvent::inverted() |
460 | */ |
461 | |
462 | QT_END_NAMESPACE |
463 | |
464 | #include "moc_qquickevents_p_p.cpp" |
465 | |