Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qquickhoverhandler.cpp
Go to the documentation of this file.
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
// Qt-Security score:significant reason:default
4
5
#
include
"qquickhoverhandler_p.h"
6
#
include
<
private
/
qquicksinglepointhandler_p_p
.
h
>
7
#
include
<
private
/
qquickdeliveryagent_p
.
h
>
8
#
include
<
private
/
qquickitem_p
.
h
>
9
10
QT_BEGIN_NAMESPACE
11
12
Q_STATIC_LOGGING_CATEGORY(lcHoverHandler,
"qt.quick.handler.hover"
)
13
14
/*!
15
\qmltype HoverHandler
16
\nativetype QQuickHoverHandler
17
\inherits SinglePointHandler
18
\inqmlmodule QtQuick
19
\ingroup qtquick-input-handlers
20
\brief Handler for mouse and tablet hover.
21
22
HoverHandler detects a hovering mouse or tablet stylus cursor.
23
24
A binding to the \l hovered property is the easiest way to react when the
25
cursor enters or leaves the \l {PointerHandler::parent}{parent} Item.
26
The \l {SinglePointHandler::point}{point} property provides more detail,
27
including the cursor position. The
28
\l {PointerDeviceHandler::acceptedDevices}{acceptedDevices},
29
\l {PointerDeviceHandler::acceptedPointerTypes}{acceptedPointerTypes},
30
and \l {PointerDeviceHandler::acceptedModifiers}{acceptedModifiers}
31
properties can be used to narrow the behavior to detect hovering of
32
specific kinds of devices or while holding a modifier key.
33
34
The \l cursorShape property allows changing the cursor whenever
35
\l hovered changes to \c true.
36
37
\sa MouseArea, PointHandler, {Qt Quick Examples - Pointer Handlers}
38
*/
39
40
class
QQuickHoverHandlerPrivate :
public
QQuickSinglePointHandlerPrivate
41
{
42
Q_DECLARE_PUBLIC(QQuickHoverHandler)
43
44
public
:
45
void
onEnabledChanged() override;
46
void
onParentChanged(QQuickItem *oldParent, QQuickItem *newParent) override;
47
48
void
updateHasHoverInChild(QQuickItem *item,
bool
hasHover);
49
};
50
51
void
QQuickHoverHandlerPrivate::onEnabledChanged()
52
{
53
Q_Q(QQuickHoverHandler);
54
55
if
(
auto
parent = q->parentItem())
56
updateHasHoverInChild(parent, enabled);
57
if
(!enabled)
58
q->setHovered(
false
);
59
60
QQuickSinglePointHandlerPrivate::onEnabledChanged();
61
}
62
63
void
QQuickHoverHandlerPrivate::onParentChanged(QQuickItem *oldParent, QQuickItem *newParent)
64
{
65
if
(oldParent)
66
updateHasHoverInChild(oldParent,
false
);
67
if
(newParent)
68
updateHasHoverInChild(newParent,
true
);
69
70
QQuickSinglePointHandlerPrivate::onParentChanged(oldParent, newParent);
71
}
72
73
void
QQuickHoverHandlerPrivate::updateHasHoverInChild(QQuickItem *item,
bool
hasHover)
74
{
75
QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
76
itemPriv->setHasHoverInChild(hasHover);
77
// The DA needs to resolve which items and handlers should now be hovered or unhovered.
78
// Marking the parent item dirty ensures that flushFrameSynchronousEvents() will be called from the render loop,
79
// even if this change is not in response to a mouse event and no item has already marked itself dirty.
80
itemPriv->dirty(QQuickItemPrivate::Content);
81
}
82
83
QQuickHoverHandler::QQuickHoverHandler(QQuickItem *parent)
84
: QQuickSinglePointHandler(*(
new
QQuickHoverHandlerPrivate), parent)
85
{
86
Q_D(QQuickHoverHandler);
87
// Tell QQuickPointerDeviceHandler::wantsPointerEvent() to ignore button state
88
d->acceptedButtons = Qt::NoButton;
89
if
(parent)
90
d->updateHasHoverInChild(parent,
true
);
91
}
92
93
QQuickHoverHandler::~QQuickHoverHandler()
94
{
95
Q_D(QQuickHoverHandler);
96
if
(
auto
parent = parentItem())
97
d->updateHasHoverInChild(parent,
false
);
98
}
99
100
/*!
101
\qmlproperty bool QtQuick::HoverHandler::blocking
102
\since 6.3
103
104
Whether this handler prevents other items or handlers behind it from
105
being hovered at the same time. This property is \c false by default.
106
*/
107
void
QQuickHoverHandler::setBlocking(
bool
blocking)
108
{
109
if
(m_blocking == blocking)
110
return
;
111
112
m_blocking = blocking;
113
emit blockingChanged();
114
}
115
116
bool
QQuickHoverHandler::event(QEvent *event)
117
{
118
switch
(event->type())
119
{
120
case
QEvent::HoverLeave:
121
setHovered(
false
);
122
setActive(
false
);
123
break
;
124
default
:
125
return
QQuickSinglePointHandler::event(event);
126
break
;
127
}
128
129
return
true
;
130
}
131
132
void
QQuickHoverHandler::componentComplete()
133
{
134
Q_D(QQuickHoverHandler);
135
QQuickSinglePointHandler::componentComplete();
136
137
if
(d->enabled) {
138
if
(
auto
parent = parentItem())
139
d->updateHasHoverInChild(parent,
true
);
140
}
141
}
142
143
bool
QQuickHoverHandler::wantsPointerEvent(QPointerEvent *event)
144
{
145
// No state change should occur if a button is being pressed or released.
146
if
(event->isSinglePointEvent() &&
static_cast
<QSinglePointEvent *>(event)->button())
147
return
false
;
148
auto
&point = event->point(0);
149
const
bool
inside = parentContains(point);
150
if
(QQuickPointerDeviceHandler::wantsPointerEvent(event) && wantsEventPoint(event, point) && inside) {
151
// assume this is a mouse or tablet event, so there's only one point
152
setPointId(point.id());
153
return
true
;
154
}
155
156
// Some hover events come from QQuickWindow::tabletEvent(). In between,
157
// some hover events come from QQuickDeliveryAgentPrivate::flushFrameSynchronousEvents(),
158
// but those look like mouse events. If a particular HoverHandler instance
159
// is filtering for tablet events only (e.g. by setting
160
// acceptedDevices:PointerDevice.Stylus), those events should not cause
161
// the hovered property to transition to false prematurely.
162
// If a QQuickPointerTabletEvent caused the hovered property to become true,
163
// then only another QQuickPointerTabletEvent can make it become false.
164
// But after kCursorOverrideTimeout ms, QQuickItemPrivate::effectiveCursorHandler()
165
// will ignore it, just in case there is no QQuickPointerTabletEvent to unset it.
166
// For example, a tablet proximity leave event could occur, but we don't deliver it to the window.
167
if
(!inside || !(m_hoveredTablet && QQuickDeliveryAgentPrivate::isMouseEvent(event)))
168
setHovered(
false
);
169
170
return
false
;
171
}
172
173
void
QQuickHoverHandler::handleEventPoint(QPointerEvent *ev, QEventPoint &point)
174
{
175
bool
hovered =
true
;
176
if
(point.state() == QEventPoint::Released &&
177
ev->pointingDevice()->pointerType() == QPointingDevice::PointerType::Finger)
178
hovered =
false
;
179
else
if
(QQuickDeliveryAgentPrivate::isTabletEvent(ev))
180
m_hoveredTablet =
true
;
181
setHovered(hovered);
182
}
183
184
/*!
185
\qmlproperty bool QtQuick::HoverHandler::hovered
186
\readonly
187
188
Holds true whenever any pointing device cursor (mouse or tablet) is within
189
the bounds of the \c parent Item, extended by the
190
\l {PointerHandler::margin}{margin}, if any.
191
*/
192
void
QQuickHoverHandler::setHovered(
bool
hovered)
193
{
194
if
(m_hovered != hovered) {
195
qCDebug(lcHoverHandler) << objectName() <<
"hovered"
<< m_hovered <<
"->"
<< hovered;
196
m_hovered = hovered;
197
if
(!hovered)
198
m_hoveredTablet =
false
;
199
emit hoveredChanged();
200
}
201
}
202
203
/*!
204
\internal
205
\qmlproperty flags QtQuick::HoverHandler::acceptedButtons
206
207
This property is not used in HoverHandler.
208
*/
209
210
/*!
211
\qmlproperty flags QtQuick::HoverHandler::acceptedDevices
212
213
The types of pointing devices that can activate the pointer handler.
214
215
By default, this property is set to
216
\l{QInputDevice::DeviceType}{PointerDevice.AllDevices}.
217
If you set it to an OR combination of device types, it will ignore pointer
218
events from the non-matching devices.
219
220
For example, an item could be made to respond to mouse hover in one way,
221
and stylus hover in another way, with two handlers:
222
223
\snippet pointerHandlers/hoverMouseOrStylus.qml 0
224
225
The available device types are as follows:
226
227
\value PointerDevice.Mouse A mouse.
228
\value PointerDevice.TouchScreen A touchscreen.
229
\value PointerDevice.TouchPad A touchpad or trackpad.
230
\value PointerDevice.Stylus A stylus on a graphics tablet.
231
\value PointerDevice.Airbrush An airbrush on a graphics tablet.
232
\value PointerDevice.Puck A digitizer with crosshairs, on a graphics tablet.
233
\value PointerDevice.AllDevices Any type of pointing device.
234
235
\note Not all platforms are yet able to distinguish mouse and touchpad; and
236
on those that do, you often want to make mouse and touchpad behavior the same.
237
238
\sa QInputDevice::DeviceType
239
*/
240
241
/*!
242
\qmlproperty flags QtQuick::HoverHandler::acceptedPointerTypes
243
244
The types of pointing instruments (generic, stylus, eraser, and so on)
245
that can activate the pointer handler.
246
247
By default, this property is set to
248
\l {QPointingDevice::PointerType} {PointerDevice.AllPointerTypes}.
249
If you set it to an OR combination of device types, it will ignore events
250
from non-matching events.
251
252
For example, you could provide feedback by changing the cursor depending on
253
whether a stylus or eraser is hovering over a graphics tablet:
254
255
\snippet pointerHandlers/hoverStylusOrEraser.qml 0
256
257
The available pointer types are as follows:
258
259
\value PointerDevice.Generic A mouse or a device that emulates a mouse.
260
\value PointerDevice.Finger A finger on a touchscreen (hover detection is unlikely).
261
\value PointerDevice.Pen A stylus on a graphics tablet.
262
\value PointerDevice.Eraser An eraser on a graphics tablet.
263
\value PointerDevice.Cursor A digitizer with crosshairs, on a graphics tablet.
264
\value PointerDevice.AllPointerTypes Any type of pointing device.
265
266
\sa QPointingDevice::PointerType
267
*/
268
269
/*!
270
\qmlproperty flags QtQuick::HoverHandler::acceptedModifiers
271
272
If this property is set, a hover event is handled only if the given keyboard
273
modifiers are pressed. The event is ignored without the modifiers.
274
275
This property is set to \c Qt.KeyboardModifierMask by default, resulting
276
in handling hover events regardless of any modifier keys.
277
278
For example, an \l[QML]{Item} could have two handlers of the same type, one
279
of which is enabled only if the required keyboard modifiers are pressed:
280
281
\snippet pointerHandlers/hoverModifiers.qml 0
282
283
The available modifiers are as follows:
284
285
\value Qt.NoModifier No modifier key is allowed.
286
\value Qt.ShiftModifier A Shift key on the keyboard must be pressed.
287
\value Qt.ControlModifier A Ctrl key on the keyboard must be pressed.
288
\value Qt.AltModifier An Alt key on the keyboard must be pressed.
289
\value Qt.MetaModifier A Meta key on the keyboard must be pressed.
290
\value Qt.KeypadModifier A keypad button must be pressed.
291
\value Qt.GroupSwitchModifier A Mode_switch key on the keyboard must be pressed.
292
X11 only (unless activated on Windows by a command line argument).
293
\value Qt.KeyboardModifierMask The handler ignores modifier keys.
294
295
\sa Qt::KeyboardModifier
296
*/
297
298
/*!
299
\since 5.15
300
\qmlproperty Qt::CursorShape QtQuick::HoverHandler::cursorShape
301
This property holds the cursor shape that will appear whenever
302
\l hovered is \c true and no other handler is overriding it.
303
304
The available cursor shapes are:
305
\list
306
\li Qt.ArrowCursor
307
\li Qt.UpArrowCursor
308
\li Qt.CrossCursor
309
\li Qt.WaitCursor
310
\li Qt.IBeamCursor
311
\li Qt.SizeVerCursor
312
\li Qt.SizeHorCursor
313
\li Qt.SizeBDiagCursor
314
\li Qt.SizeFDiagCursor
315
\li Qt.SizeAllCursor
316
\li Qt.BlankCursor
317
\li Qt.SplitVCursor
318
\li Qt.SplitHCursor
319
\li Qt.PointingHandCursor
320
\li Qt.ForbiddenCursor
321
\li Qt.WhatsThisCursor
322
\li Qt.BusyCursor
323
\li Qt.OpenHandCursor
324
\li Qt.ClosedHandCursor
325
\li Qt.DragCopyCursor
326
\li Qt.DragMoveCursor
327
\li Qt.DragLinkCursor
328
\endlist
329
330
The default value of this property is not set, which allows any active
331
handler on the same \e parent item to determine the cursor shape.
332
This property can be reset to the initial condition by setting it to
333
\c undefined.
334
335
If any handler with defined \c cursorShape is
336
\l {PointerHandler::active}{active}, that cursor will appear.
337
Else if the HoverHandler has a defined \c cursorShape, that cursor will appear.
338
Otherwise, the \l {QQuickItem::cursor()}{cursor} of \e parent item will appear.
339
340
\note When this property has not been set, or has been set to \c undefined,
341
if you read the value it will return \c Qt.ArrowCursor.
342
343
\sa Qt::CursorShape, QQuickItem::cursor()
344
*/
345
346
/*!
347
\internal
348
\qmlproperty flags HoverHandler::dragThreshold
349
350
This property is not used in HoverHandler.
351
*/
352
353
/*!
354
\qmlproperty bool QtQuick::HoverHandler::enabled
355
356
If a HoverHandler is disabled, it will reject all events
357
and no signals will be emitted.
358
359
If a HoverHandler's \l parent is \l {Item::enabled}{disabled}, the
360
HoverHandler continues to react to hover events by default. This is because
361
hover feedback effects and tooltips may be useful even when a control is
362
disabled. If you want to disable the HoverHandler when its parent is
363
disabled, you can add a binding:
364
365
\qml
366
Item {
367
HoverHandler {
368
enabled: parent.enabled
369
}
370
}
371
\endqml
372
*/
373
374
QT_END_NAMESPACE
375
376
#
include
"moc_qquickhoverhandler_p.cpp"
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtdeclarative
src
quick
handlers
qquickhoverhandler.cpp
Generated on
for Qt by
1.18.0