238
238
QObject::connect(this, &QQuickMouseArea::enabledChanged,
239
239
this, &InverseMouseAreaType::update);
240
QObject::connect(this, &QQuickMouseArea::visibleChanged,
241
this, &InverseMouseAreaType::update);
243
* Also connect to windowChanged() to get the proper window to filter
245
QObject::connect(this, &QQuickMouseArea::windowChanged,
246
this, &InverseMouseAreaType::resetFilterOnWindowUpdate);
241
248
if (!m_sensingArea) {
242
249
// get sensing area upon parent change
258
void InverseMouseAreaType::updateEventFilter(bool enable)
260
m_filteredEvent = false;
261
if (!enable && m_filterHost) {
262
m_filterHost->removeEventFilter(this);
263
m_filterHost.clear();
266
QQuickWindow *currentWindow = window();
267
if (!currentWindow || (m_filterHost == currentWindow)) {
272
m_filterHost->removeEventFilter(this);
274
currentWindow->installEventFilter(this);
275
m_filterHost = currentWindow;
261
289
// update sensing area
290
if (!m_sensingArea) {
263
291
m_sensingArea = QuickUtils::instance().rootItem(this);
293
updateEventFilter(isEnabled() && isVisible() && m_topmostItem);
297
Slot connected to windowChanged signal to refresh filter host.
299
void InverseMouseAreaType::resetFilterOnWindowUpdate(QQuickWindow *win)
302
updateEventFilter(m_topmostItem);
266
305
void InverseMouseAreaType::componentComplete()
268
307
QQuickMouseArea::componentComplete();
269
// by now the parents shoudl have been resolved so we can look after the
308
// by now the parents should have been resolved so we can look after the
270
309
// topmost component for the sensingArea in case it has not been set yet
276
315
* Translate mouse, wheel and hover event positions to component's local coordinates.
278
QEvent *InverseMouseAreaType::mapEventToArea(QObject *target, QEvent *event)
317
QEvent *InverseMouseAreaType::mapEventToArea(QObject *target, QEvent *event, QPoint &point)
319
QQuickItem *targetItem = qobject_cast<QQuickItem*>(target);
320
// target can be the QQuickView or QQuickWindow, then we need to get the root item from it
322
QQuickView *view = qobject_cast<QQuickView*>(target);
324
targetItem = view->rootObject();
326
QQuickWindow *window = qobject_cast<QQuickWindow*>(target);
328
targetItem = window->contentItem();
333
m_filteredEvent = true;
280
335
switch (event->type()) {
281
336
case QEvent::MouseButtonPress:
282
337
case QEvent::MouseButtonRelease:
283
338
case QEvent::MouseButtonDblClick:
284
339
case QEvent::MouseMove:
285
if (target != this) {
340
if (targetItem != this) {
286
341
// translate coordinates to local
287
342
QMouseEvent *ev = static_cast<QMouseEvent*>(event);
288
343
QMouseEvent *mev = new QMouseEvent(ev->type(),
292
347
ev->button(), ev->buttons(), ev->modifiers());
296
352
case QEvent::Wheel:
297
if (target != this) {
353
if (targetItem != this) {
298
354
QWheelEvent *ev = static_cast<QWheelEvent*>(event);
299
355
QWheelEvent *wev = new QWheelEvent(mapFromScene(ev->globalPos()), ev->globalPos(),
300
356
ev->delta(), ev->buttons(), ev->modifiers(), ev->orientation());
304
361
case QEvent::HoverEnter:
305
362
case QEvent::HoverLeave:
306
363
case QEvent::HoverMove: {
307
QQuickItem *item = qobject_cast<QQuickItem*>(target);
308
if (item && item != this) {
364
if (targetItem && targetItem != this) {
309
365
QHoverEvent *ev = static_cast<QHoverEvent*>(event);
310
QPointF spos = item->mapToScene(ev->posF());
311
QPointF sopos = item->mapToScene(ev->oldPosF());
366
QPointF spos = targetItem->mapToScene(ev->posF());
367
QPointF sopos = targetItem->mapToScene(ev->oldPosF());
312
368
QHoverEvent *hev = new QHoverEvent(ev->type(),
313
369
mapFromScene(spos),
314
370
mapFromScene(sopos),
315
371
ev->modifiers());
376
// convert touch events into mouse events and continue handling as such
377
case QEvent::TouchBegin: {
378
QTouchEvent *tev = static_cast<QTouchEvent*>(event);
379
QList<QTouchEvent::TouchPoint> points = tev->touchPoints();
380
const QTouchEvent::TouchPoint &primaryPoint = points.first();
381
m_touchId = primaryPoint.id();
382
QPointF pos = targetItem->mapToScene(primaryPoint.pos());
383
QMouseEvent *mev = new QMouseEvent(QEvent::MouseButtonPress,
385
primaryPoint.scenePos(),
386
primaryPoint.screenPos(),
387
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
391
case QEvent::TouchUpdate: {
392
QTouchEvent *tev = static_cast<QTouchEvent*>(event);
393
QList<QTouchEvent::TouchPoint> points = tev->touchPoints();
394
const QTouchEvent::TouchPoint &primaryPoint = points.first();
395
QPointF pos = targetItem->mapToScene(primaryPoint.pos());
396
QMouseEvent *mev = new QMouseEvent(QEvent::MouseMove,
398
primaryPoint.scenePos(),
399
primaryPoint.screenPos(),
400
Qt::NoButton, Qt::NoButton, Qt::NoModifier);
404
case QEvent::TouchEnd: {
405
QMouseEvent *mev = 0;
406
QTouchEvent *tev = static_cast<QTouchEvent*>(event);
407
QList<QTouchEvent::TouchPoint> points = tev->touchPoints();
408
for (int i = 0; i < points.count(); i++) {
409
const QTouchEvent::TouchPoint &point = points.at(i);
410
if (point.id() != m_touchId) {
413
QPointF pos = targetItem->mapToScene(point.pos());
414
mev = new QMouseEvent(QEvent::MouseButtonRelease,
418
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
425
m_filteredEvent = false;
325
432
bool InverseMouseAreaType::eventFilter(QObject *object, QEvent *event)
330
434
if (object != this)
332
436
bool captured = true;
333
QEvent *mappedEvent = mapEventToArea(object, event);
438
QEvent *mappedEvent = mapEventToArea(object, event, point);
335
switch (event->type()) {
440
switch (mappedEvent->type()) {
336
441
case QEvent::MouseButtonPress:
337
442
mousePressEvent(static_cast<QMouseEvent*>(mappedEvent));
377
484
// overload QQuickMouseArea mousePress event as the original one sets containsMouse
378
485
// to true automatically, however ion our case this can be false in case the press
379
486
// happens inside the "hole"
380
if (!m_topmostItem || (m_topmostItem && contains(event->localPos()))) {
487
if (!m_topmostItem || (m_topmostItem && m_filteredEvent && contains(event->localPos()))) {
381
488
QQuickMouseArea::mousePressEvent(event);
383
490
// we do not consume the mouse event
418
525
sensing = QuickUtils::instance().rootItem(this);
419
526
if (sensing != m_sensingArea) {
420
bool oldTopItem = m_topmostItem;
421
setTopmostItem(false);
527
// clear previous filter
528
updateEventFilter(false);
422
529
m_sensingArea = sensing;
423
setTopmostItem(oldTopItem);
530
updateEventFilter(m_topmostItem);
424
531
Q_EMIT sensingAreaChanged();
441
548
if (m_topmostItem != value) {
442
549
m_topmostItem = value;
443
QObject *sensingArea = (m_sensingArea && m_sensingArea != QuickUtils::instance().rootItem(this)) ?
444
static_cast<QObject*>(m_sensingArea) : QGuiApplication::instance();
446
sensingArea->installEventFilter(this);
448
sensingArea->removeEventFilter(this);
550
updateEventFilter(m_topmostItem);
551
Q_EMIT topmostItemChanged();
458
560
QPointF scenePos = mapToScene(point);
459
561
QRectF oskRect = QGuiApplication::inputMethod()->keyboardRectangle();
460
bool pointInArea = QQuickItem::contains(point);
562
bool pointInArea = QQuickMouseArea::contains(point);
461
563
bool pointInOSK = oskRect.contains(scenePos);
462
564
bool pointOutArea = (m_sensingArea && m_sensingArea->contains(m_sensingArea->mapFromScene(scenePos)));
463
565
return !pointInArea && !pointInOSK && pointOutArea;