~zsombi/ubuntu-ui-toolkit/combobutton

« back to all changes in this revision

Viewing changes to modules/Ubuntu/Components/plugin/inversemouseareatype.cpp

  • Committer: Zsombor Egri
  • Date: 2014-03-25 07:23:36 UTC
  • mfrom: (938.13.15 ubuntu-ui-toolkit)
  • Revision ID: zsombor.egri@canonical.com-20140325072336-ldp9ag50j5ermh7j
trunk merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
237
237
     */
238
238
    QObject::connect(this, &QQuickMouseArea::enabledChanged,
239
239
                     this, &InverseMouseAreaType::update);
 
240
    QObject::connect(this, &QQuickMouseArea::visibleChanged,
 
241
                     this, &InverseMouseAreaType::update);
 
242
    /*
 
243
     * Also connect to windowChanged() to get the proper window to filter
 
244
     */
 
245
    QObject::connect(this, &QQuickMouseArea::windowChanged,
 
246
                     this, &InverseMouseAreaType::resetFilterOnWindowUpdate);
240
247
 
241
248
    if (!m_sensingArea) {
242
249
        // get sensing area upon parent change
248
255
{
249
256
}
250
257
 
 
258
void InverseMouseAreaType::updateEventFilter(bool enable)
 
259
{
 
260
    m_filteredEvent = false;
 
261
    if (!enable && m_filterHost) {
 
262
        m_filterHost->removeEventFilter(this);
 
263
        m_filterHost.clear();
 
264
 
 
265
    } else if (enable) {
 
266
        QQuickWindow *currentWindow = window();
 
267
        if (!currentWindow || (m_filterHost == currentWindow)) {
 
268
            return;
 
269
        }
 
270
 
 
271
        if (m_filterHost) {
 
272
            m_filterHost->removeEventFilter(this);
 
273
        }
 
274
        currentWindow->installEventFilter(this);
 
275
        m_filterHost = currentWindow;
 
276
    }
 
277
}
 
278
 
251
279
 
252
280
/*!
253
281
  \internal
259
287
        return;
260
288
    }
261
289
    // update sensing area
262
 
    if (!m_sensingArea)
 
290
    if (!m_sensingArea) {
263
291
        m_sensingArea = QuickUtils::instance().rootItem(this);
 
292
    }
 
293
    updateEventFilter(isEnabled() && isVisible() && m_topmostItem);
 
294
}
 
295
/*!
 
296
  \internal
 
297
  Slot connected to windowChanged signal to refresh filter host.
 
298
 */
 
299
void InverseMouseAreaType::resetFilterOnWindowUpdate(QQuickWindow *win)
 
300
{
 
301
    Q_UNUSED(win);
 
302
    updateEventFilter(m_topmostItem);
264
303
}
265
304
 
266
305
void InverseMouseAreaType::componentComplete()
267
306
{
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
271
310
    m_ready = true;
272
311
    update();
275
314
/*
276
315
 * Translate mouse, wheel and hover event positions to component's local coordinates.
277
316
 */
278
 
QEvent *InverseMouseAreaType::mapEventToArea(QObject *target, QEvent *event)
 
317
QEvent *InverseMouseAreaType::mapEventToArea(QObject *target, QEvent *event, QPoint &point)
279
318
{
 
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
 
321
    if (!targetItem) {
 
322
        QQuickView *view = qobject_cast<QQuickView*>(target);
 
323
        if (view) {
 
324
            targetItem = view->rootObject();
 
325
        } else {
 
326
            QQuickWindow *window = qobject_cast<QQuickWindow*>(target);
 
327
            if (window) {
 
328
                targetItem = window->contentItem();
 
329
            }
 
330
        }
 
331
    }
 
332
    Q_ASSERT(target);
 
333
    m_filteredEvent = true;
 
334
 
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(),
290
345
                                   ev->windowPos(),
291
346
                                   ev->screenPos(),
292
347
                                   ev->button(), ev->buttons(), ev->modifiers());
 
348
            point = mev->pos();
293
349
            return mev;
294
350
        }
295
351
        break;
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());
 
357
            point = wev->pos();
301
358
            return wev;
302
359
        }
303
360
        break;
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());
 
372
            point = hev->pos();
316
373
            return hev;
317
374
        }
318
375
        } break;
 
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,
 
384
                        mapFromScene(pos),
 
385
                        primaryPoint.scenePos(),
 
386
                        primaryPoint.screenPos(),
 
387
                        Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
 
388
        point = mev->pos();
 
389
        return mev;
 
390
        } break;
 
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,
 
397
                        mapFromScene(pos),
 
398
                        primaryPoint.scenePos(),
 
399
                        primaryPoint.screenPos(),
 
400
                        Qt::NoButton, Qt::NoButton, Qt::NoModifier);
 
401
        point = mev->pos();
 
402
        return mev;
 
403
        } break;
 
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) {
 
411
                continue;
 
412
            }
 
413
            QPointF pos = targetItem->mapToScene(point.pos());
 
414
            mev = new QMouseEvent(QEvent::MouseButtonRelease,
 
415
                            mapFromScene(pos),
 
416
                            point.scenePos(),
 
417
                            point.screenPos(),
 
418
                            Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
 
419
            break;
 
420
        }
 
421
        point = mev->pos();
 
422
        return mev;
 
423
        } break;
319
424
    default:
 
425
        m_filteredEvent = false;
 
426
        point = QPoint();
320
427
        break;
321
428
    }
322
429
    return event;
324
431
 
325
432
bool InverseMouseAreaType::eventFilter(QObject *object, QEvent *event)
326
433
{
327
 
    if (!isEnabled())
328
 
        return false;
329
 
 
330
434
    if (object != this)
331
435
    {
332
436
        bool captured = true;
333
 
        QEvent *mappedEvent = mapEventToArea(object, event);
 
437
        QPoint point;
 
438
        QEvent *mappedEvent = mapEventToArea(object, event, point);
334
439
 
335
 
        switch (event->type()) {
 
440
        switch (mappedEvent->type()) {
336
441
        case QEvent::MouseButtonPress:
337
442
            mousePressEvent(static_cast<QMouseEvent*>(mappedEvent));
338
443
            break;
365
470
            event->setAccepted(mappedEvent->isAccepted());
366
471
            delete mappedEvent;
367
472
        }
368
 
        if (captured && !propagateComposedEvents()) {
369
 
            return event->isAccepted();
 
473
        m_filteredEvent = false;
 
474
        if (captured && event->isAccepted() && contains(point)) {
 
475
            // consume the event
 
476
            return true;
370
477
        }
371
478
    }
372
 
    return QQuickMouseArea::eventFilter(object, event);
 
479
    return false;
373
480
}
374
481
 
375
482
void InverseMouseAreaType::mousePressEvent(QMouseEvent *event)
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);
382
489
    } else {
383
490
        // we do not consume the mouse event
391
498
void InverseMouseAreaType::mouseDoubleClickEvent(QMouseEvent *event)
392
499
{
393
500
    // same as with mousePressEvent
394
 
    if (!m_topmostItem || (m_topmostItem && contains(event->localPos()))) {
 
501
    if (!m_topmostItem || (m_topmostItem && m_filteredEvent && contains(event->localPos()))) {
395
502
        QQuickMouseArea::mouseDoubleClickEvent(event);
396
503
    } else {
397
504
        // we do not consume the mouse event
417
524
    if (!sensing)
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();
425
532
    }
426
533
}
440
547
{
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();
445
 
        if (m_topmostItem) {
446
 
            sensingArea->installEventFilter(this);
447
 
        } else {
448
 
            sensingArea->removeEventFilter(this);
449
 
        }
 
550
        updateEventFilter(m_topmostItem);
 
551
        Q_EMIT topmostItemChanged();
450
552
    }
451
553
}
452
554
 
457
559
{
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;