diff --git a/autotests/libinput/input_event_test.cpp b/autotests/libinput/input_event_test.cpp --- a/autotests/libinput/input_event_test.cpp +++ b/autotests/libinput/input_event_test.cpp @@ -23,6 +23,8 @@ #include +Q_DECLARE_METATYPE(KWin::SwitchEvent::State); + using namespace KWin; using namespace KWin::LibInput; @@ -36,6 +38,8 @@ void testInitKeyEvent(); void testInitWheelEvent_data(); void testInitWheelEvent(); + void testInitSwitchEvent_data(); + void testInitSwitchEvent(); }; void InputEventsTest::testInitMouseEvent_data() @@ -149,5 +153,32 @@ } +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.h b/debug_console.h --- a/debug_console.h +++ b/debug_console.h @@ -150,6 +150,8 @@ void swipeGestureEnd(quint32 time) override; void swipeGestureCancelled(quint32 time) override; + void switchEvent(SwitchEvent *event) override; + private: QTextEdit *m_textEdit; }; diff --git a/debug_console.cpp b/debug_console.cpp --- a/debug_console.cpp +++ b/debug_console.cpp @@ -459,6 +459,43 @@ 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/input.h b/input.h --- a/input.h +++ b/input.h @@ -47,6 +47,7 @@ class PointerInputRedirection; class TouchInputRedirection; class WindowSelectorFilter; +class SwitchEvent; namespace Decoration { @@ -360,6 +361,8 @@ virtual bool swipeGestureEnd(quint32 time); virtual bool swipeGestureCancelled(quint32 time); + virtual bool switchEvent(SwitchEvent *event); + protected: void passToWaylandServer(QKeyEvent *event); }; diff --git a/input.cpp b/input.cpp --- a/input.cpp +++ b/input.cpp @@ -167,6 +167,12 @@ return false; } +bool InputEventFilter::switchEvent(SwitchEvent *event) +{ + Q_UNUSED(event) + return false; +} + void InputEventFilter::passToWaylandServer(QKeyEvent *event) { Q_ASSERT(waylandServer()); @@ -1766,6 +1772,15 @@ 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_event.h b/input_event.h --- a/input_event.h +++ b/input_event.h @@ -124,6 +124,33 @@ 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.cpp b/input_event.cpp --- a/input_event.cpp +++ b/input_event.cpp @@ -51,4 +51,13 @@ 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_spy.h b/input_event_spy.h --- a/input_event_spy.h +++ b/input_event_spy.h @@ -31,6 +31,7 @@ class KeyEvent; class MouseEvent; class WheelEvent; +class SwitchEvent; /** @@ -81,6 +82,8 @@ virtual void swipeGestureEnd(quint32 time); virtual void swipeGestureCancelled(quint32 time); + virtual void switchEvent(SwitchEvent *event); + }; diff --git a/input_event_spy.cpp b/input_event_spy.cpp --- a/input_event_spy.cpp +++ b/input_event_spy.cpp @@ -116,4 +116,9 @@ Q_UNUSED(time) } +void InputEventSpy::switchEvent(SwitchEvent *event) +{ + Q_UNUSED(event) +} + }