File indexing completed on 2024-12-22 05:16:04

0001 /*
0002     SPDX-FileCopyrightText: 2022 Janet Blackquill <uhhadd@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "maskmousearea.h"
0008 #include <QQuickItemGrabResult>
0009 
0010 struct MaskMouseArea::Private {
0011     QImage maskImage;
0012     bool containsMouse = false;
0013 };
0014 
0015 MaskMouseArea::MaskMouseArea(QQuickItem *parent)
0016     : QQuickItem(parent)
0017     , d(new Private)
0018 {
0019     setAcceptHoverEvents(true);
0020     setAcceptedMouseButtons(Qt::AllButtons);
0021     updateMask();
0022     connect(this, &QQuickItem::parentChanged, this, &MaskMouseArea::updateMask);
0023 }
0024 
0025 MaskMouseArea::~MaskMouseArea()
0026 {
0027 }
0028 
0029 void MaskMouseArea::updateMask()
0030 {
0031     if (parentItem() == nullptr || parentItem()->height() < 1) {
0032         return;
0033     }
0034 
0035     auto result = parentItem()->grabToImage();
0036     connect(
0037         result.get(),
0038         &QQuickItemGrabResult::ready,
0039         this,
0040         [result, this] {
0041             d->maskImage = result->image();
0042         },
0043         Qt::SingleShotConnection /* Otherwise leak */);
0044 }
0045 
0046 void MaskMouseArea::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
0047 {
0048     Q_UNUSED(newGeometry)
0049     Q_UNUSED(oldGeometry)
0050 
0051     updateMask();
0052 }
0053 
0054 bool MaskMouseArea::contains(const QPointF &point) const
0055 {
0056     if (!QQuickItem::contains(point) || d->maskImage.isNull()) {
0057         return false;
0058     }
0059 
0060     QPoint rounded = point.toPoint();
0061     const int x = rounded.x(), y = rounded.y();
0062 
0063     if (x < 0 || x >= d->maskImage.width()) {
0064         return false;
0065     }
0066     if (y < 0 || y >= d->maskImage.height()) {
0067         return false;
0068     }
0069 
0070     return d->maskImage.pixel(x, y) != 0;
0071 }
0072 
0073 void MaskMouseArea::mousePressEvent(QMouseEvent *event)
0074 {
0075     event->accept();
0076 }
0077 
0078 void MaskMouseArea::mouseReleaseEvent(QMouseEvent *event)
0079 {
0080     if (!contains(event->position())) {
0081         return;
0082     }
0083 
0084     Q_EMIT tapped();
0085 }
0086 
0087 void MaskMouseArea::hoverEnterEvent(QHoverEvent *event)
0088 {
0089     Q_UNUSED(event)
0090     d->containsMouse = true;
0091     Q_EMIT hoveredChanged();
0092 }
0093 
0094 void MaskMouseArea::hoverLeaveEvent(QHoverEvent *event)
0095 {
0096     Q_UNUSED(event)
0097     d->containsMouse = false;
0098     Q_EMIT hoveredChanged();
0099 }
0100 
0101 bool MaskMouseArea::hovered() const
0102 {
0103     return d->containsMouse;
0104 }