diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 872e61f8..f3893998 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -49,6 +49,7 @@
#include "ui/MxcMediaProxy.h"
#include "ui/NhekoCursorShape.h"
#include "ui/NhekoDropArea.h"
+#include "ui/NhekoEventObserver.h"
#include "ui/NhekoGlobalObject.h"
#include "ui/UIA.h"
#include "voip/WebRTCSession.h"
@@ -164,6 +165,7 @@ MainWindow::registerQmlTypes()
qmlRegisterType<DelegateChooser>("im.nheko", 1, 0, "DelegateChooser");
qmlRegisterType<NhekoDropArea>("im.nheko", 1, 0, "NhekoDropArea");
qmlRegisterType<NhekoCursorShape>("im.nheko", 1, 0, "CursorShape");
+ qmlRegisterType<NhekoEventObserver>("im.nheko", 1, 0, "EventObserver");
qmlRegisterType<MxcAnimatedImage>("im.nheko", 1, 0, "MxcAnimatedImage");
qmlRegisterType<MxcMediaProxy>("im.nheko", 1, 0, "MxcMedia");
qmlRegisterType<RoomDirectoryModel>("im.nheko", 1, 0, "RoomDirectoryModel");
diff --git a/src/ui/NhekoEventObserver.cpp b/src/ui/NhekoEventObserver.cpp
new file mode 100644
index 00000000..5e67cec4
--- /dev/null
+++ b/src/ui/NhekoEventObserver.cpp
@@ -0,0 +1,61 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "NhekoEventObserver.h"
+
+#include <QMouseEvent>
+
+#include "Logging.h"
+
+NhekoEventObserver::NhekoEventObserver(QQuickItem *parent)
+ : QQuickItem(parent)
+{
+ setFiltersChildMouseEvents(true);
+}
+
+bool
+NhekoEventObserver::childMouseEventFilter(QQuickItem * /*item*/, QEvent *event)
+{
+ // nhlog::ui()->debug("Touched {}", item->metaObject()->className());
+
+ auto setTouched = [this](bool touched) {
+ if (touched != this->wasTouched_) {
+ this->wasTouched_ = touched;
+ emit wasTouchedChanged();
+ }
+ };
+
+ // see
+ // https://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/quicktemplates2/qquickscrollview.cpp?id=7f29e89c26ae2babc358b1c4e6f965af6ec759f4#n471
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchEnd:
+ setTouched(true);
+ break;
+
+ case QEvent::MouseButtonPress:
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized) {
+ setTouched(false);
+ }
+ break;
+
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
+ setTouched(false);
+ break;
+
+ case QEvent::HoverEnter:
+ case QEvent::HoverMove:
+ case QEvent::Wheel:
+ setTouched(false);
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
diff --git a/src/ui/NhekoEventObserver.h b/src/ui/NhekoEventObserver.h
new file mode 100644
index 00000000..6d14f30f
--- /dev/null
+++ b/src/ui/NhekoEventObserver.h
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <QQuickItem>
+
+class NhekoEventObserver : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool wasTouched READ wasTouched NOTIFY wasTouchedChanged)
+
+public:
+ explicit NhekoEventObserver(QQuickItem *parent = 0);
+
+ bool childMouseEventFilter(QQuickItem *item, QEvent *event) override;
+
+private:
+ bool wasTouched() { return wasTouched_; }
+
+ bool wasTouched_ = false;
+
+signals:
+ void wasTouchedChanged();
+};
|