diff --git a/autotests/libinput/input_event_test.cpp b/autotests/libinput/input_event_test.cpp index f588016f9d..c9373aa3c2 100644 --- a/autotests/libinput/input_event_test.cpp +++ b/autotests/libinput/input_event_test.cpp @@ -23,6 +23,8 @@ along with this program. If not, see . #include +Q_DECLARE_METATYPE(KWin::SwitchEvent::State); + using namespace KWin; using namespace KWin::LibInput; @@ -36,6 +38,8 @@ private Q_SLOTS: void testInitKeyEvent(); void testInitWheelEvent_data(); void testInitWheelEvent(); + void testInitSwitchEvent_data(); + void testInitSwitchEvent(); }; void InputEventsTest::testInitMouseEvent_data() @@ -149,5 +153,32 @@ void InputEventsTest::testInitWheelEvent() } +void InputEventsTest::testInitSwitchEvent_data() +{ + QTest::addColumn("state"); + QTest::addColumn("timestamp"); + QTest::addColumn("micro"); + + QTest::newRow("on") << SwitchEvent::State::On << 23u << quint64{23456790}; + QTest::newRow("off") << SwitchEvent::State::Off << 456892u << quint64{45689235987}; +} + +void InputEventsTest::testInitSwitchEvent() +{ + // this test verifies that a SwitchEvent is constructed correctly + libinput_device device; + Device d(&device); + + QFETCH(SwitchEvent::State, state); + QFETCH(quint32, timestamp); + QFETCH(quint64, micro); + SwitchEvent event(state, timestamp, micro, &d); + + QCOMPARE(event.state(), state); + QCOMPARE(event.timestamp(), ulong(timestamp)); + QCOMPARE(event.timestampMicroseconds(), micro); + QCOMPARE(event.device(), &d); +} + QTEST_GUILESS_MAIN(InputEventsTest) #include "input_event_test.moc" diff --git a/debug_console.cpp b/debug_console.cpp index bbc8c5a9c8..44aed0f9f0 100644 --- a/debug_console.cpp +++ b/debug_console.cpp @@ -459,6 +459,43 @@ void DebugConsoleFilter::swipeGestureCancelled(quint32 time) m_textEdit->ensureCursorVisible(); } +void DebugConsoleFilter::switchEvent(SwitchEvent *event) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A hardware switch (e.g. notebook lid) got toggled", "Switch toggled"))); + text.append(timestampRow(event->timestamp())); + if (event->timestampMicroseconds() != 0) { + text.append(timestampRowUsec(event->timestampMicroseconds())); + } +#if HAVE_INPUT + text.append(deviceRow(event->device())); + QString switchName; + if (event->device()->isLidSwitch()) { + switchName = i18nc("Name of a hardware switch", "Notebook lid"); + } else if (event->device()->isTabletModeSwitch()) { + switchName = i18nc("Name of a hardware switch", "Tablet mode"); + } + text.append(tableRow(i18nc("A hardware switch", "Switch"), switchName)); +#endif + QString switchState; + switch (event->state()) { + case SwitchEvent::State::Off: + switchState = i18nc("The hardware switch got turned off", "Off"); + break; + case SwitchEvent::State::On: + switchState = i18nc("The hardware switch got turned on", "On"); + break; + default: + Q_UNREACHABLE(); + } + text.append(tableRow(i18nc("State of a hardware switch (on/off)", "State"), switchState)); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); +} + DebugConsole::DebugConsole() : QWidget() , m_ui(new Ui::DebugConsole) diff --git a/debug_console.h b/debug_console.h index e5eeb09f1a..27503d3395 100644 --- a/debug_console.h +++ b/debug_console.h @@ -150,6 +150,8 @@ class DebugConsoleFilter : public InputEventSpy void swipeGestureEnd(quint32 time) override; void swipeGestureCancelled(quint32 time) override; + void switchEvent(SwitchEvent *event) override; + private: QTextEdit *m_textEdit; }; diff --git a/input.cpp b/input.cpp index 4778390e99..cd105ecf1e 100644 --- a/input.cpp +++ b/input.cpp @@ -167,6 +167,12 @@ bool InputEventFilter::swipeGestureCancelled(quint32 time) return false; } +bool InputEventFilter::switchEvent(SwitchEvent *event) +{ + Q_UNUSED(event) + return false; +} + void InputEventFilter::passToWaylandServer(QKeyEvent *event) { Q_ASSERT(waylandServer()); @@ -1766,6 +1772,15 @@ void InputRedirection::setupLibInput() connect(conn, &LibInput::Connection::touchMotion, m_touch, &TouchInputRedirection::processMotion); connect(conn, &LibInput::Connection::touchCanceled, m_touch, &TouchInputRedirection::cancel); connect(conn, &LibInput::Connection::touchFrame, m_touch, &TouchInputRedirection::frame); + auto handleSwitchEvent = [this] (SwitchEvent::State state, quint32 time, quint64 timeMicroseconds, LibInput::Device *device) { + SwitchEvent event(state, time, timeMicroseconds, device); + processSpies(std::bind(&InputEventSpy::switchEvent, std::placeholders::_1, &event)); + processFilters(std::bind(&InputEventFilter::switchEvent, std::placeholders::_1, &event)); + }; + connect(conn, &LibInput::Connection::switchToggledOn, this, + std::bind(handleSwitchEvent, SwitchEvent::State::On, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + connect(conn, &LibInput::Connection::switchToggledOff, this, + std::bind(handleSwitchEvent, SwitchEvent::State::Off, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); if (screens()) { setupLibInputWithScreens(); } else { diff --git a/input.h b/input.h index 9aa8047219..da1ad0028c 100644 --- a/input.h +++ b/input.h @@ -47,6 +47,7 @@ class PointerConstraintsFilter; class PointerInputRedirection; class TouchInputRedirection; class WindowSelectorFilter; +class SwitchEvent; namespace Decoration { @@ -360,6 +361,8 @@ class KWIN_EXPORT InputEventFilter virtual bool swipeGestureEnd(quint32 time); virtual bool swipeGestureCancelled(quint32 time); + virtual bool switchEvent(SwitchEvent *event); + protected: void passToWaylandServer(QKeyEvent *event); }; diff --git a/input_event.cpp b/input_event.cpp index 8de4284597..b8a2d7c97c 100644 --- a/input_event.cpp +++ b/input_event.cpp @@ -51,4 +51,13 @@ KeyEvent::KeyEvent(QEvent::Type type, Qt::Key key, Qt::KeyboardModifiers modifie setTimestamp(timestamp); } +SwitchEvent::SwitchEvent(State state, quint32 timestamp, quint64 timestampMicroseconds, LibInput::Device* device) + : QInputEvent(QEvent::User) + , m_state(state) + , m_timestampMicroseconds(timestampMicroseconds) + , m_device(device) +{ + setTimestamp(timestamp); +} + } diff --git a/input_event.h b/input_event.h index 548fcfd7f2..7854a10885 100644 --- a/input_event.h +++ b/input_event.h @@ -124,6 +124,33 @@ class KeyEvent : public QKeyEvent Qt::KeyboardModifiers m_modifiersRelevantForShortcuts = Qt::KeyboardModifiers(); }; +class SwitchEvent : public QInputEvent +{ +public: + enum class State { + Off, + On + }; + explicit SwitchEvent(State state, quint32 timestamp, quint64 timestampMicroseconds, LibInput::Device *device); + + State state() const { + return m_state; + } + + quint64 timestampMicroseconds() const { + return m_timestampMicroseconds; + } + + LibInput::Device *device() const { + return m_device; + } + +private: + State m_state; + quint64 m_timestampMicroseconds; + LibInput::Device *m_device; +}; + } #endif diff --git a/input_event_spy.cpp b/input_event_spy.cpp index a7538ab3b2..bb139c0574 100644 --- a/input_event_spy.cpp +++ b/input_event_spy.cpp @@ -116,4 +116,9 @@ void InputEventSpy::swipeGestureCancelled(quint32 time) Q_UNUSED(time) } +void InputEventSpy::switchEvent(SwitchEvent *event) +{ + Q_UNUSED(event) +} + } diff --git a/input_event_spy.h b/input_event_spy.h index 843e148ffa..32ba36ba32 100644 --- a/input_event_spy.h +++ b/input_event_spy.h @@ -31,6 +31,7 @@ namespace KWin class KeyEvent; class MouseEvent; class WheelEvent; +class SwitchEvent; /** @@ -81,6 +82,8 @@ class KWIN_EXPORT InputEventSpy virtual void swipeGestureEnd(quint32 time); virtual void swipeGestureCancelled(quint32 time); + virtual void switchEvent(SwitchEvent *event); + };