| 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 | \nativetype 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 | \nativetype 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 | \nativetype 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 | |