diff --git a/backends/hwcomposer/hwcomposer_backend.cpp b/backends/hwcomposer/hwcomposer_backend.cpp index 1af78c2345..bfbd205000 100644 --- a/backends/hwcomposer/hwcomposer_backend.cpp +++ b/backends/hwcomposer/hwcomposer_backend.cpp @@ -29,6 +29,8 @@ along with this program. If not, see . #include #include #include +// Qt +#include // hybris/android #include #include @@ -41,6 +43,103 @@ along with this program. If not, see . namespace KWin { +BacklightInputEventFilter::BacklightInputEventFilter(HwcomposerBackend *backend) + : InputEventFilter() + , m_backend(backend) +{ +} + +BacklightInputEventFilter::~BacklightInputEventFilter() = default; + +bool BacklightInputEventFilter::pointerEvent(QMouseEvent *event, quint32 nativeButton) +{ + Q_UNUSED(event) + Q_UNUSED(nativeButton) + if (!m_backend->isBacklightOff()) { + return false; + } + toggleBacklight(); + return true; +} + +bool BacklightInputEventFilter::wheelEvent(QWheelEvent *event) +{ + Q_UNUSED(event) + if (!m_backend->isBacklightOff()) { + return false; + } + toggleBacklight(); + return true; +} + +bool BacklightInputEventFilter::keyEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_PowerOff && event->type() == QEvent::KeyRelease) { + toggleBacklight(); + return true; + } + return m_backend->isBacklightOff(); +} + +bool BacklightInputEventFilter::touchDown(quint32 id, const QPointF &pos, quint32 time) +{ + Q_UNUSED(pos) + Q_UNUSED(time) + if (!m_backend->isBacklightOff()) { + return false; + } + if (m_touchPoints.isEmpty()) { + if (!m_doubleTapTimer.isValid()) { + // this is the first tap + m_doubleTapTimer.start(); + } else { + if (m_doubleTapTimer.elapsed() < qApp->doubleClickInterval()) { + m_secondTap = true; + } else { + // took too long. Let's consider it a new click + m_doubleTapTimer.restart(); + } + } + } else { + // not a double tap + m_doubleTapTimer.invalidate(); + m_secondTap = false; + } + m_touchPoints << id; + return true; +} + +bool BacklightInputEventFilter::touchUp(quint32 id, quint32 time) +{ + Q_UNUSED(time) + m_touchPoints.removeAll(id); + if (!m_backend->isBacklightOff()) { + return false; + } + if (m_touchPoints.isEmpty() && m_doubleTapTimer.isValid() && m_secondTap) { + if (m_doubleTapTimer.elapsed() < qApp->doubleClickInterval()) { + toggleBacklight(); + } + m_doubleTapTimer.invalidate(); + m_secondTap = false; + } + return true; +} + +bool BacklightInputEventFilter::touchMotion(quint32 id, const QPointF &pos, quint32 time) +{ + Q_UNUSED(id) + Q_UNUSED(pos) + Q_UNUSED(time) + return m_backend->isBacklightOff(); +} + +void BacklightInputEventFilter::toggleBacklight() +{ + // queued to not modify the list of event filters while filtering + QMetaObject::invokeMethod(m_backend, "toggleBlankOutput", Qt::QueuedConnection); +} + HwcomposerBackend::HwcomposerBackend(QObject *parent) : AbstractBackend(parent) { @@ -137,16 +236,8 @@ void HwcomposerBackend::init() initLights(); toggleBlankOutput(); - connect(input(), &InputRedirection::keyStateChanged, this, - [this] (quint32 key, InputRedirection::KeyboardKeyState state) { - if (state != InputRedirection::KeyboardKeyState::KeyboardKeyReleased) { - return; - } - if (key == KEY_POWER) { - toggleBlankOutput(); - } - } - ); + m_filter.reset(new BacklightInputEventFilter(this)); + input()->prepandInputEventFilter(m_filter.data()); // get display configuration auto output = createOutput(hwcDevice); diff --git a/backends/hwcomposer/hwcomposer_backend.h b/backends/hwcomposer/hwcomposer_backend.h index f4b1477962..5c8fc24e5e 100644 --- a/backends/hwcomposer/hwcomposer_backend.h +++ b/backends/hwcomposer/hwcomposer_backend.h @@ -20,7 +20,9 @@ along with this program. If not, see . #ifndef KWIN_HWCOMPOSER_BACKEND_H #define KWIN_HWCOMPOSER_BACKEND_H #include "abstract_backend.h" +#include "input.h" +#include #include #include @@ -40,6 +42,7 @@ namespace KWin { class HwcomposerWindow; +class BacklightInputEventFilter; class HwcomposerBackend : public AbstractBackend { @@ -74,6 +77,10 @@ public: void waitVSync(); void wakeVSync(); + bool isBacklightOff() const { + return m_outputBlank; + } + Q_SIGNALS: void outputBlankChanged(); @@ -92,6 +99,7 @@ private: bool m_hasVsync = false; QMutex m_vsyncMutex; QWaitCondition m_vsyncWaitCondition; + QScopedPointer m_filter; }; class HwcomposerWindow : public HWComposerNativeWindow @@ -108,6 +116,27 @@ private: hwc_display_contents_1_t **m_list; }; +class BacklightInputEventFilter : public InputEventFilter +{ +public: + BacklightInputEventFilter(HwcomposerBackend *backend); + virtual ~BacklightInputEventFilter(); + + bool pointerEvent(QMouseEvent *event, quint32 nativeButton) override; + bool wheelEvent(QWheelEvent *event) override; + bool keyEvent(QKeyEvent *event) override; + bool touchDown(quint32 id, const QPointF &pos, quint32 time) override; + bool touchMotion(quint32 id, const QPointF &pos, quint32 time) override; + bool touchUp(quint32 id, quint32 time) override; + +private: + void toggleBacklight(); + HwcomposerBackend *m_backend; + QElapsedTimer m_doubleTapTimer; + QVector m_touchPoints; + bool m_secondTap = false; +}; + } #endif