diff --git a/autotests/libinput/CMakeLists.txt b/autotests/libinput/CMakeLists.txt index d281ee6290..8a8b048c9e 100644 --- a/autotests/libinput/CMakeLists.txt +++ b/autotests/libinput/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(${Libinput_INCLUDE_DIRS}) -add_library(LibInputTestObjects STATIC ../../src/libinput/device.cpp ../../src/libinput/events.cpp mock_libinput.cpp) +add_library(LibInputTestObjects STATIC ../../src/libinput/device.cpp ../../src/libinput/events.cpp ../../src/inputdevice.cpp mock_libinput.cpp) target_link_libraries(LibInputTestObjects Qt::Test Qt::Widgets Qt::DBus Qt::Gui KF5::ConfigCore) target_include_directories(LibInputTestObjects PUBLIC ${CMAKE_SOURCE_DIR}/src) diff --git a/autotests/libinput/mock_libinput.cpp b/autotests/libinput/mock_libinput.cpp index 39968ecdb7..6e0ebc55dd 100644 --- a/autotests/libinput/mock_libinput.cpp +++ b/autotests/libinput/mock_libinput.cpp @@ -936,3 +936,11 @@ libinput_device_group_get_user_data(struct libinput_device_group *group) Q_UNUSED(group); return nullptr; } + +void +libinput_device_led_update(struct libinput_device *device, + enum libinput_led leds) +{ + Q_UNUSED(device) + Q_UNUSED(leds) +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f77ff6f6c..6f6c5a17df 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -56,6 +56,8 @@ set(kwin_SRCS input.cpp input_event.cpp input_event_spy.cpp + inputbackend.cpp + inputdevice.cpp inputmethod.cpp inputpanelv1client.cpp inputpanelv1integration.cpp @@ -74,6 +76,7 @@ set(kwin_SRCS libinput/device.cpp libinput/events.cpp libinput/libinput_logging.cpp + libinput/libinputbackend.cpp linux_dmabuf.cpp main.cpp modifier_only_shortcuts.cpp diff --git a/src/debug_console.cpp b/src/debug_console.cpp index 6525d3a198..ea6fe677e6 100644 --- a/src/debug_console.cpp +++ b/src/debug_console.cpp @@ -9,10 +9,9 @@ #include "debug_console.h" #include "composite.h" #include "input_event.h" +#include "inputdevice.h" #include "internal_client.h" #include "keyboard_input.h" -#include "libinput/connection.h" -#include "libinput/device.h" #include "main.h" #include "scene.h" #include "subsurfacemonitor.h" @@ -147,7 +146,7 @@ static QString buttonToString(Qt::MouseButton button) } } -static QString deviceRow(LibInput::Device *device) +static QString deviceRow(InputDevice *device) { if (!device) { return tableRow(i18n("Input Device"), i18nc("The input device of the event is not known", "Unknown")); @@ -600,10 +599,8 @@ DebugConsole::DebugConsole() m_ui->surfacesView->setModel(new SurfaceTreeModel(this)); m_ui->clipboardContent->setModel(new DataSourceModel(this)); m_ui->primaryContent->setModel(new DataSourceModel(this)); - if (kwinApp()->usesLibinput()) { - m_ui->inputDevicesView->setModel(new InputDeviceModel(this)); - m_ui->inputDevicesView->setItemDelegate(new DebugConsoleDelegate(this)); - } + m_ui->inputDevicesView->setModel(new InputDeviceModel(this)); + m_ui->inputDevicesView->setItemDelegate(new DebugConsoleDelegate(this)); m_ui->quitButton->setIcon(QIcon::fromTheme(QStringLiteral("application-exit"))); m_ui->tabWidget->setTabIcon(0, QIcon::fromTheme(QStringLiteral("view-list-tree"))); m_ui->tabWidget->setTabIcon(1, QIcon::fromTheme(QStringLiteral("view-list-tree"))); @@ -613,9 +610,6 @@ DebugConsole::DebugConsole() m_ui->tabWidget->setTabEnabled(2, false); m_ui->tabWidget->setTabEnabled(6, false); } - if (!kwinApp()->usesLibinput()) { - m_ui->tabWidget->setTabEnabled(3, false); - } connect(m_ui->quitButton, &QAbstractButton::clicked, this, &DebugConsole::deleteLater); connect(m_ui->tabWidget, &QTabWidget::currentChanged, this, @@ -1486,22 +1480,22 @@ QVariant SurfaceTreeModel::data(const QModelIndex &index, int role) const InputDeviceModel::InputDeviceModel(QObject *parent) : QAbstractItemModel(parent) - , m_devices(LibInput::Connection::self()->devices()) + , m_devices(input()->devices()) { for (auto it = m_devices.constBegin(); it != m_devices.constEnd(); ++it) { setupDeviceConnections(*it); } - auto c = LibInput::Connection::self(); - connect(c, &LibInput::Connection::deviceAdded, this, - [this] (LibInput::Device *d) { + + connect(input(), &InputRedirection::deviceAdded, this, + [this] (InputDevice *d) { beginInsertRows(QModelIndex(), m_devices.count(), m_devices.count()); m_devices << d; setupDeviceConnections(d); endInsertRows(); } ); - connect(c, &LibInput::Connection::deviceRemoved, this, - [this] (LibInput::Device *d) { + connect(input(), &InputRedirection::deviceRemoved, this, + [this] (InputDevice *d) { const int index = m_devices.indexOf(d); if (index == -1) { return; @@ -1528,17 +1522,16 @@ QVariant InputDeviceModel::data(const QModelIndex &index, int role) const return QVariant(); } if (!index.parent().isValid() && index.column() == 0) { - const auto devices = LibInput::Connection::self()->devices(); - if (index.row() >= devices.count()) { + if (index.row() >= m_devices.count()) { return QVariant(); } if (role == Qt::DisplayRole) { - return devices.at(index.row())->name(); + return m_devices.at(index.row())->name(); } } if (index.parent().isValid()) { if (role == Qt::DisplayRole) { - const auto device = LibInput::Connection::self()->devices().at(index.parent().row()); + const auto device = m_devices.at(index.parent().row()); const auto property = device->metaObject()->property(index.row()); if (index.column() == 0) { return property.name(); @@ -1559,12 +1552,12 @@ QModelIndex InputDeviceModel::index(int row, int column, const QModelIndex &pare if (parent.internalId() & s_propertyBitMask) { return QModelIndex(); } - if (row >= LibInput::Connection::self()->devices().at(parent.row())->metaObject()->propertyCount()) { + if (row >= m_devices.at(parent.row())->metaObject()->propertyCount()) { return QModelIndex(); } return createIndex(row, column, quint32(row + 1) << 16 | parent.internalId()); } - if (row >= LibInput::Connection::self()->devices().count()) { + if (row >= m_devices.count()) { return QModelIndex(); } return createIndex(row, column, row + 1); @@ -1573,13 +1566,13 @@ QModelIndex InputDeviceModel::index(int row, int column, const QModelIndex &pare int InputDeviceModel::rowCount(const QModelIndex &parent) const { if (!parent.isValid()) { - return LibInput::Connection::self()->devices().count(); + return m_devices.count(); } if (parent.internalId() & s_propertyBitMask) { return 0; } - return LibInput::Connection::self()->devices().at(parent.row())->metaObject()->propertyCount(); + return m_devices.at(parent.row())->metaObject()->propertyCount(); } QModelIndex InputDeviceModel::parent(const QModelIndex &child) const @@ -1593,7 +1586,7 @@ QModelIndex InputDeviceModel::parent(const QModelIndex &child) const void InputDeviceModel::slotPropertyChanged() { - const auto device = static_cast(sender()); + const auto device = static_cast(sender()); for (int i = 0; i < device->metaObject()->propertyCount(); ++i) { const QMetaProperty metaProperty = device->metaObject()->property(i); @@ -1605,7 +1598,7 @@ void InputDeviceModel::slotPropertyChanged() } } -void InputDeviceModel::setupDeviceConnections(LibInput::Device *device) +void InputDeviceModel::setupDeviceConnections(InputDevice *device) { QMetaMethod handler = metaObject()->method(metaObject()->indexOfMethod("slotPropertyChanged()")); for (int i = 0; i < device->metaObject()->propertyCount(); ++i) { diff --git a/src/debug_console.h b/src/debug_console.h index 23d32ba207..7bd91cc0ab 100644 --- a/src/debug_console.h +++ b/src/debug_console.h @@ -163,11 +163,6 @@ private: QTextEdit *m_textEdit; }; -namespace LibInput -{ -class Device; -} - class InputDeviceModel : public QAbstractItemModel { Q_OBJECT @@ -185,8 +180,8 @@ private Q_SLOTS: void slotPropertyChanged(); private: - void setupDeviceConnections(LibInput::Device *device); - QVector m_devices; + void setupDeviceConnections(InputDevice *device); + QList m_devices; }; class DataSourceModel : public QAbstractItemModel diff --git a/src/input.cpp b/src/input.cpp index f99df474c8..538c1c8163 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -14,6 +14,7 @@ #include "globalshortcuts.h" #include "input_event.h" #include "input_event_spy.h" +#include "inputbackend.h" #include "keyboard_input.h" #include "main.h" #include "pointer_input.h" @@ -47,12 +48,14 @@ #include #include #include -#include #include //screenlocker #include // Qt +#include +#include +#include #include #include #include @@ -1634,6 +1637,12 @@ class TabletInputFilter : public QObject, public InputEventFilter public: TabletInputFilter() { + const auto devices = input()->devices(); + for (InputDevice *device : devices) { + integrateDevice(device); + } + connect(input(), &InputRedirection::deviceAdded, this, &TabletInputFilter::integrateDevice); + connect(input(), &InputRedirection::deviceRemoved, this, &TabletInputFilter::removeDevice); } static KWaylandServer::TabletSeatV2Interface *findTabletSeat() @@ -1646,9 +1655,10 @@ public: return manager->seat(findSeat()); } - void integrateDevice(LibInput::Device *device) + void integrateDevice(InputDevice *inputDevice) { - if (!device->isTabletTool() && !device->isTabletPad()) { + auto device = qobject_cast(inputDevice); + if (!device || (!device->isTabletTool() && !device->isTabletPad())) { return; } @@ -1678,19 +1688,20 @@ public: } } - void removeDevice(LibInput::Device *device) + void removeDevice(InputDevice *inputDevice) { - auto deviceGroup = libinput_device_get_device_group(device->device()); - libinput_device_group_set_user_data(deviceGroup, nullptr); - } + auto device = qobject_cast(inputDevice); + if (device) { + auto deviceGroup = libinput_device_get_device_group(device->device()); + libinput_device_group_set_user_data(deviceGroup, nullptr); - void removeDeviceBySysName(const QString &sysname) - { - KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat(); - if (tabletSeat) - tabletSeat->removeDevice(sysname); - else - qCCritical(KWIN_CORE) << "Could not find tablet to remove" << sysname; + KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat(); + if (tabletSeat) { + tabletSeat->removeDevice(device->sysName()); + } else { + qCCritical(KWIN_CORE) << "Could not find tablet to remove" << device->sysName(); + } + } } KWaylandServer::TabletToolV2Interface::Type getType(const KWin::TabletToolId &tabletToolId) { @@ -2140,21 +2151,15 @@ InputRedirection::InputRedirection(QObject *parent) qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); - if (Application::usesLibinput()) { - setupLibInput(); - } + setupInputBackends(); connect(kwinApp(), &Application::workspaceCreated, this, &InputRedirection::setupWorkspace); } InputRedirection::~InputRedirection() { - if (m_libInput) { - m_libInput->deleteLater(); - - m_libInputThread->quit(); - m_libInputThread->wait(); - delete m_libInputThread; - } + qDeleteAll(m_inputBackends); + m_inputBackends.clear(); + m_inputDevices.clear(); s_self = nullptr; qDeleteAll(m_filters); @@ -2190,6 +2195,10 @@ void InputRedirection::uninstallInputEventSpy(InputEventSpy *spy) void InputRedirection::init() { + m_inputConfigWatcher = KConfigWatcher::create(InputConfig::self()->inputConfig()); + connect(m_inputConfigWatcher.data(), &KConfigWatcher::configChanged, + this, &InputRedirection::handleInputConfigChanged); + m_shortcuts->init(); } @@ -2298,6 +2307,9 @@ void InputRedirection::setupWorkspace() m_pointer->init(); m_touch->init(); m_tablet->init(); + + updateLeds(m_keyboard->xkb()->leds()); + connect(m_keyboard, &KeyboardInputRedirection::ledsChanged, this, &InputRedirection::updateLeds); } setupTouchpadShortcuts(); setupInputFilters(); @@ -2489,178 +2501,211 @@ void InputRedirection::setupInputFilters() if (waylandServer()) { installInputEventFilter(new WindowActionInputFilter); installInputEventFilter(new ForwardInputFilter); - - if (m_libInput) { - m_tabletSupport = new TabletInputFilter; - const QVector devices = m_libInput->devices(); - for (LibInput::Device *dev : devices) { - m_tabletSupport->integrateDevice(dev); - } - connect(m_libInput, &LibInput::Connection::deviceAdded, m_tabletSupport, &TabletInputFilter::integrateDevice); - connect(m_libInput, &LibInput::Connection::deviceRemoved, m_tabletSupport, &TabletInputFilter::removeDevice); - - connect(m_libInput, &LibInput::Connection::deviceRemovedSysName, m_tabletSupport, &TabletInputFilter::removeDeviceBySysName); - installInputEventFilter(m_tabletSupport); - } + installInputEventFilter(new TabletInputFilter); } } void InputRedirection::handleInputConfigChanged(const KConfigGroup &group) { if (group.name() == QLatin1String("Keyboard")) { - reconfigure(); + m_keyboard->reconfigure(); } } -void InputRedirection::reconfigure() +void InputRedirection::updateLeds(LEDs leds) { - if (Application::usesLibinput()) { - auto inputConfig = m_inputConfigWatcher->config(); - const auto config = inputConfig->group(QStringLiteral("Keyboard")); - const int delay = config.readEntry("RepeatDelay", 660); - const int rate = int(config.readEntry("RepeatRate", 25.0)); - const QString repeatMode = config.readEntry("KeyRepeat", "repeat"); - // when the clients will repeat the character or turn repeat key events into an accent character selection, we want - // to tell the clients that we are indeed repeating keys. - const bool enabled = repeatMode == QLatin1String("accent") || repeatMode == QLatin1String("repeat"); + if (m_leds != leds) { + m_leds = leds; - waylandServer()->seat()->keyboard()->setRepeatInfo(enabled ? rate : 0, delay); + for (InputDevice *device : qAsConst(m_inputDevices)) { + device->setLeds(leds); + } } } -void InputRedirection::setupLibInput() +void InputRedirection::handleInputDeviceAdded(InputDevice *device) { - if (!Application::usesLibinput()) { - return; - } - if (m_libInput) { - return; + connect(device, &InputDevice::keyChanged, m_keyboard, &KeyboardInputRedirection::processKey); + + connect(device, &InputDevice::pointerMotionAbsolute, + m_pointer, &PointerInputRedirection::processMotionAbsolute); + connect(device, &InputDevice::pointerMotion, + m_pointer, &PointerInputRedirection::processMotion); + connect(device, &InputDevice::pointerButtonChanged, + m_pointer, &PointerInputRedirection::processButton); + connect(device, &InputDevice::pointerAxisChanged, + m_pointer, &PointerInputRedirection::processAxis); + connect(device, &InputDevice::pinchGestureBegin, + m_pointer, &PointerInputRedirection::processPinchGestureBegin); + connect(device, &InputDevice::pinchGestureUpdate, + m_pointer, &PointerInputRedirection::processPinchGestureUpdate); + connect(device, &InputDevice::pinchGestureEnd, + m_pointer, &PointerInputRedirection::processPinchGestureEnd); + connect(device, &InputDevice::pinchGestureCancelled, + m_pointer, &PointerInputRedirection::processPinchGestureCancelled); + connect(device, &InputDevice::swipeGestureBegin, + m_pointer, &PointerInputRedirection::processSwipeGestureBegin); + connect(device, &InputDevice::swipeGestureUpdate, + m_pointer, &PointerInputRedirection::processSwipeGestureUpdate); + connect(device, &InputDevice::swipeGestureEnd, + m_pointer, &PointerInputRedirection::processSwipeGestureEnd); + connect(device, &InputDevice::swipeGestureCancelled, + m_pointer, &PointerInputRedirection::processSwipeGestureCancelled); + connect(device, &InputDevice::holdGestureBegin, + m_pointer, &PointerInputRedirection::processHoldGestureBegin); + connect(device, &InputDevice::holdGestureEnd, + m_pointer, &PointerInputRedirection::processHoldGestureEnd); + connect(device, &InputDevice::holdGestureCancelled, + m_pointer, &PointerInputRedirection::processHoldGestureCancelled); + + connect(device, &InputDevice::touchDown, m_touch, &TouchInputRedirection::processDown); + connect(device, &InputDevice::touchUp, m_touch, &TouchInputRedirection::processUp); + connect(device, &InputDevice::touchMotion, m_touch, &TouchInputRedirection::processMotion); + connect(device, &InputDevice::touchCanceled, m_touch, &TouchInputRedirection::cancel); + connect(device, &InputDevice::touchFrame, m_touch, &TouchInputRedirection::frame); + + auto handleSwitchEvent = [this] (SwitchEvent::State state, quint32 time, quint64 timeMicroseconds, InputDevice *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(device, &InputDevice::switchToggledOn, this, + std::bind(handleSwitchEvent, SwitchEvent::State::On, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + connect(device, &InputDevice::switchToggledOff, this, + std::bind(handleSwitchEvent, SwitchEvent::State::Off, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + + connect(device, &InputDevice::tabletToolEvent, + m_tablet, &TabletInputRedirection::tabletToolEvent); + connect(device, &InputDevice::tabletToolButtonEvent, + m_tablet, &TabletInputRedirection::tabletToolButtonEvent); + connect(device, &InputDevice::tabletPadButtonEvent, + m_tablet, &TabletInputRedirection::tabletPadButtonEvent); + connect(device, &InputDevice::tabletPadRingEvent, + m_tablet, &TabletInputRedirection::tabletPadRingEvent); + connect(device, &InputDevice::tabletPadStripEvent, + m_tablet, &TabletInputRedirection::tabletPadStripEvent); + + device->setLeds(m_leds); + + m_inputDevices.append(device); + Q_EMIT deviceAdded(device); + + updateAvailableInputDevices(); +} + +void InputRedirection::handleInputDeviceRemoved(InputDevice *device) +{ + m_inputDevices.removeOne(device); + Q_EMIT deviceRemoved(device); + + updateAvailableInputDevices(); +} + +void InputRedirection::updateAvailableInputDevices() +{ + const bool hasKeyboard = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) { + return device->isKeyboard(); + }); + if (m_hasKeyboard != hasKeyboard) { + m_hasKeyboard = hasKeyboard; + Q_EMIT hasKeyboardChanged(hasKeyboard); } - m_libInputThread = new QThread(); - m_libInputThread->setObjectName(QStringLiteral("libinput-connection")); - m_libInputThread->start(); + const bool hasAlphaNumericKeyboard = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) { + return device->isAlphaNumericKeyboard(); + }); + if (m_hasAlphaNumericKeyboard != hasAlphaNumericKeyboard) { + m_hasAlphaNumericKeyboard = hasAlphaNumericKeyboard; + Q_EMIT hasAlphaNumericKeyboardChanged(hasAlphaNumericKeyboard); + } - LibInput::Connection *conn = LibInput::Connection::create(this); - m_libInput = conn; - m_libInput->moveToThread(m_libInputThread); + const bool hasPointer = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) { + return device->isPointer(); + }); + if (m_hasPointer != hasPointer) { + m_hasPointer = hasPointer; + Q_EMIT hasPointerChanged(hasPointer); + } - if (conn) { - conn->setInputConfig(InputConfig::self()->inputConfig()); - conn->updateLEDs(m_keyboard->xkb()->leds()); - waylandServer()->updateKeyState(m_keyboard->xkb()->leds()); - connect(m_keyboard, &KeyboardInputRedirection::ledsChanged, waylandServer(), &WaylandServer::updateKeyState); - connect(m_keyboard, &KeyboardInputRedirection::ledsChanged, conn, &LibInput::Connection::updateLEDs); - connect(conn, &LibInput::Connection::eventsRead, this, - [this] { - m_libInput->processEvents(); - }, Qt::QueuedConnection + const bool hasTouch = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) { + return device->isTouch(); + }); + if (m_hasTouch != hasTouch) { + m_hasTouch = hasTouch; + Q_EMIT hasTouchChanged(hasTouch); + } + + const bool hasTabletModeSwitch = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) { + return device->isTabletModeSwitch(); + }); + if (m_hasTabletModeSwitch != hasTabletModeSwitch) { + m_hasTabletModeSwitch = hasTabletModeSwitch; + Q_EMIT hasTabletModeSwitchChanged(hasTabletModeSwitch); + } +} + +void InputRedirection::toggleTouchpads() +{ + bool changed = false; + m_touchpadsEnabled = !m_touchpadsEnabled; + for (InputDevice *device : qAsConst(m_inputDevices)) { + if (!device->isTouchpad()) { + continue; + } + const bool old = device->isEnabled(); + device->setEnabled(m_touchpadsEnabled); + if (old != device->isEnabled()) { + changed = true; + } + } + if (changed) { + // send OSD message + QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.plasmashell"), + QStringLiteral("/org/kde/osdService"), + QStringLiteral("org.kde.osdService"), + QStringLiteral("touchpadEnabledChanged") ); - conn->setup(); - connect(conn, &LibInput::Connection::pointerButtonChanged, m_pointer, &PointerInputRedirection::processButton); - connect(conn, &LibInput::Connection::pointerAxisChanged, m_pointer, &PointerInputRedirection::processAxis); - connect(conn, &LibInput::Connection::pinchGestureBegin, m_pointer, &PointerInputRedirection::processPinchGestureBegin); - connect(conn, &LibInput::Connection::pinchGestureUpdate, m_pointer, &PointerInputRedirection::processPinchGestureUpdate); - connect(conn, &LibInput::Connection::pinchGestureEnd, m_pointer, &PointerInputRedirection::processPinchGestureEnd); - connect(conn, &LibInput::Connection::pinchGestureCancelled, m_pointer, &PointerInputRedirection::processPinchGestureCancelled); - connect(conn, &LibInput::Connection::swipeGestureBegin, m_pointer, &PointerInputRedirection::processSwipeGestureBegin); - connect(conn, &LibInput::Connection::swipeGestureUpdate, m_pointer, &PointerInputRedirection::processSwipeGestureUpdate); - connect(conn, &LibInput::Connection::swipeGestureEnd, m_pointer, &PointerInputRedirection::processSwipeGestureEnd); - connect(conn, &LibInput::Connection::swipeGestureCancelled, m_pointer, &PointerInputRedirection::processSwipeGestureCancelled); - connect(conn, &LibInput::Connection::holdGestureBegin, m_pointer, &PointerInputRedirection::processHoldGestureBegin); - connect(conn, &LibInput::Connection::holdGestureEnd, m_pointer, &PointerInputRedirection::processHoldGestureEnd); - connect(conn, &LibInput::Connection::holdGestureCancelled, m_pointer, &PointerInputRedirection::processHoldGestureCancelled); - connect(conn, &LibInput::Connection::keyChanged, m_keyboard, &KeyboardInputRedirection::processKey); - connect(conn, &LibInput::Connection::pointerMotion, m_pointer, &PointerInputRedirection::processMotion); - connect(conn, &LibInput::Connection::pointerMotionAbsolute, m_pointer, &PointerInputRedirection::processMotionAbsolute); - connect(conn, &LibInput::Connection::touchDown, m_touch, &TouchInputRedirection::processDown); - connect(conn, &LibInput::Connection::touchUp, m_touch, &TouchInputRedirection::processUp); - 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)); + msg.setArguments({m_touchpadsEnabled}); + QDBusConnection::sessionBus().asyncCall(msg); + } +} - connect(conn, &LibInput::Connection::tabletToolEvent, - m_tablet, &TabletInputRedirection::tabletToolEvent); - connect(conn, &LibInput::Connection::tabletToolButtonEvent, - m_tablet, &TabletInputRedirection::tabletToolButtonEvent); - connect(conn, &LibInput::Connection::tabletPadButtonEvent, - m_tablet, &TabletInputRedirection::tabletPadButtonEvent); - connect(conn, &LibInput::Connection::tabletPadRingEvent, - m_tablet, &TabletInputRedirection::tabletPadRingEvent); - connect(conn, &LibInput::Connection::tabletPadStripEvent, - m_tablet, &TabletInputRedirection::tabletPadStripEvent); +void InputRedirection::enableTouchpads() +{ + if (!m_touchpadsEnabled) { + toggleTouchpads(); + } +} - if (screens()) { - setupLibInputWithScreens(); - } else { - connect(kwinApp(), &Application::screensCreated, this, &InputRedirection::setupLibInputWithScreens); - } - if (auto s = findSeat()) { - // Workaround for QTBUG-54371: if there is no real keyboard Qt doesn't request virtual keyboard - s->setHasKeyboard(true); - s->setHasPointer(conn->hasPointer()); - s->setHasTouch(conn->hasTouch()); - connect(conn, &LibInput::Connection::hasAlphaNumericKeyboardChanged, this, - [this] (bool set) { - if (m_libInput->isSuspended()) { - return; - } - // TODO: this should update the seat, only workaround for QTBUG-54371 - Q_EMIT hasAlphaNumericKeyboardChanged(set); - } - ); - connect(conn, &LibInput::Connection::hasTabletModeSwitchChanged, this, - [this] (bool set) { - if (m_libInput->isSuspended()) { - return; - } - Q_EMIT hasTabletModeSwitchChanged(set); - } - ); - connect(conn, &LibInput::Connection::hasPointerChanged, this, - [this, s] (bool set) { - if (m_libInput->isSuspended()) { - return; - } - s->setHasPointer(set); - } - ); - connect(conn, &LibInput::Connection::hasTouchChanged, this, - [this, s] (bool set) { - if (m_libInput->isSuspended()) { - return; - } - s->setHasTouch(set); - } - ); - } - connect(kwinApp()->platform()->session(), &Session::activeChanged, m_libInput, [this](bool active) { - if (!active) { - m_libInput->deactivate(); - } - }); +void InputRedirection::disableTouchpads() +{ + if (m_touchpadsEnabled) { + toggleTouchpads(); + } +} - m_inputConfigWatcher = KConfigWatcher::create(InputConfig::self()->inputConfig()); - connect(m_inputConfigWatcher.data(), &KConfigWatcher::configChanged, - this, &InputRedirection::handleInputConfigChanged); - reconfigure(); +void InputRedirection::addInputBackend(InputBackend *inputBackend) +{ + Q_ASSERT(!m_inputBackends.contains(inputBackend)); + m_inputBackends.append(inputBackend); + + connect(inputBackend, &InputBackend::deviceAdded, this, &InputRedirection::handleInputDeviceAdded); + connect(inputBackend, &InputBackend::deviceRemoved, this, &InputRedirection::handleInputDeviceRemoved); + + inputBackend->setConfig(InputConfig::self()->inputConfig()); + inputBackend->initialize(); +} + +void InputRedirection::setupInputBackends() +{ + InputBackend *inputBackend = kwinApp()->platform()->createInputBackend(); + if (inputBackend) { + addInputBackend(inputBackend); } } void InputRedirection::setupTouchpadShortcuts() { - if (!m_libInput) { - return; - } QAction *touchpadToggleAction = new QAction(this); QAction *touchpadOnAction = new QAction(this); QAction *touchpadOffAction = new QAction(this); @@ -2687,40 +2732,29 @@ void InputRedirection::setupTouchpadShortcuts() registerShortcut(Qt::Key_TouchpadOn, touchpadOnAction); registerShortcut(Qt::Key_TouchpadOff, touchpadOffAction); #endif - connect(touchpadToggleAction, &QAction::triggered, m_libInput, &LibInput::Connection::toggleTouchpads); - connect(touchpadOnAction, &QAction::triggered, m_libInput, &LibInput::Connection::enableTouchpads); - connect(touchpadOffAction, &QAction::triggered, m_libInput, &LibInput::Connection::disableTouchpads); + connect(touchpadToggleAction, &QAction::triggered, this, &InputRedirection::toggleTouchpads); + connect(touchpadOnAction, &QAction::triggered, this, &InputRedirection::enableTouchpads); + connect(touchpadOffAction, &QAction::triggered, this, &InputRedirection::disableTouchpads); } bool InputRedirection::hasAlphaNumericKeyboard() { - if (m_libInput) { - return m_libInput->hasAlphaNumericKeyboard(); - } - return true; + return m_hasAlphaNumericKeyboard; +} + +bool InputRedirection::hasPointer() const +{ + return m_hasPointer; +} + +bool InputRedirection::hasTouch() const +{ + return m_hasTouch; } bool InputRedirection::hasTabletModeSwitch() { - if (m_libInput) { - return m_libInput->hasTabletModeSwitch(); - } - return false; -} - -void InputRedirection::setupLibInputWithScreens() -{ - if (!screens() || !m_libInput) { - return; - } - m_libInput->setScreenSize(screens()->size()); - m_libInput->updateScreens(); - connect(screens(), &Screens::sizeChanged, this, - [this] { - m_libInput->setScreenSize(screens()->size()); - } - ); - connect(screens(), &Screens::changed, m_libInput, &LibInput::Connection::updateScreens); + return m_hasTabletModeSwitch; } Qt::MouseButtons InputRedirection::qtButtonStates() const diff --git a/src/input.h b/src/input.h index 0fc605dd56..eaf15f080e 100644 --- a/src/input.h +++ b/src/input.h @@ -42,7 +42,6 @@ class TouchInputRedirection; class WindowSelectorFilter; class SwitchEvent; class TabletEvent; -class TabletInputFilter; class TabletToolId; class TabletPadId; @@ -51,11 +50,8 @@ namespace Decoration class DecoratedClientImpl; } -namespace LibInput -{ - class Connection; - class Device; -} +class InputBackend; +class InputDevice; /** * @brief This class is responsible for redirecting incoming input to the surface which currently @@ -221,14 +217,24 @@ public: return m_touch; } + QList devices() const; + bool hasAlphaNumericKeyboard(); + bool hasPointer() const; + bool hasTouch() const; bool hasTabletModeSwitch(); void startInteractiveWindowSelection(std::function callback, const QByteArray &cursorName); void startInteractivePositionSelection(std::function callback); bool isSelectingWindow() const; + void toggleTouchpads(); + void enableTouchpads(); + void disableTouchpads(); + Q_SIGNALS: + void deviceAdded(InputDevice *device); + void deviceRemoved(InputDevice *device); /** * @brief Emitted when the global pointer position changed * @@ -267,30 +273,35 @@ Q_SIGNALS: */ void keyStateChanged(quint32 keyCode, InputRedirection::KeyboardKeyState state); + void hasKeyboardChanged(bool set); void hasAlphaNumericKeyboardChanged(bool set); + void hasPointerChanged(bool set); + void hasTouchChanged(bool set); void hasTabletModeSwitchChanged(bool set); private Q_SLOTS: void handleInputConfigChanged(const KConfigGroup &group); + void handleInputDeviceAdded(InputDevice *device); + void handleInputDeviceRemoved(InputDevice *device); private: - void setupLibInput(); + void setupInputBackends(); void setupTouchpadShortcuts(); - void setupLibInputWithScreens(); void setupWorkspace(); - void reconfigure(); void setupInputFilters(); void installInputEventFilter(InputEventFilter *filter); + void updateLeds(LEDs leds); + void updateAvailableInputDevices(); + void addInputBackend(InputBackend *inputBackend); KeyboardInputRedirection *m_keyboard; PointerInputRedirection *m_pointer; TabletInputRedirection *m_tablet; TouchInputRedirection *m_touch; - TabletInputFilter *m_tabletSupport = nullptr; GlobalShortcutsManager *m_shortcuts; - LibInput::Connection *m_libInput = nullptr; - QThread *m_libInputThread = nullptr; + QList m_inputBackends; + QList m_inputDevices; WindowSelectorFilter *m_windowSelector = nullptr; @@ -298,6 +309,14 @@ private: QVector m_spies; KConfigWatcher::Ptr m_inputConfigWatcher; + LEDs m_leds; + bool m_hasKeyboard = false; + bool m_hasAlphaNumericKeyboard = false; + bool m_hasPointer = false; + bool m_hasTouch = false; + bool m_hasTabletModeSwitch = false; + bool m_touchpadsEnabled = true; + KWIN_SINGLETON(InputRedirection) friend InputRedirection *input(); friend class DecorationEventFilter; @@ -491,6 +510,11 @@ InputRedirection *input() return InputRedirection::s_self; } +inline QList InputRedirection::devices() const +{ + return m_inputDevices; +} + template inline void InputRedirection::registerShortcut(const QKeySequence &shortcut, QAction *action, T *receiver, Slot slot) { diff --git a/src/input_event.cpp b/src/input_event.cpp index c1603c66fb..b6d023adfb 100644 --- a/src/input_event.cpp +++ b/src/input_event.cpp @@ -14,7 +14,7 @@ namespace KWin MouseEvent::MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, quint32 timestamp, const QSizeF &delta, const QSizeF &deltaNonAccelerated, - quint64 timestampMicroseconds, LibInput::Device *device) + quint64 timestampMicroseconds, InputDevice *device) : QMouseEvent(type, pos, pos, button, buttons, modifiers) , m_delta(delta) , m_deltaUnccelerated(deltaNonAccelerated) @@ -26,7 +26,7 @@ MouseEvent::MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton bu WheelEvent::WheelEvent(const QPointF &pos, qreal delta, qint32 discreteDelta, Qt::Orientation orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, InputRedirection::PointerAxisSource source, - quint32 timestamp, LibInput::Device *device) + quint32 timestamp, InputDevice *device) : QWheelEvent(pos, pos, QPoint(), (orientation == Qt::Horizontal) ? QPoint(delta, 0) : QPoint(0, delta), delta, orientation, buttons, modifiers) , m_device(device) , m_orientation(orientation) @@ -38,14 +38,14 @@ WheelEvent::WheelEvent(const QPointF &pos, qreal delta, qint32 discreteDelta, Qt } KeyEvent::KeyEvent(QEvent::Type type, Qt::Key key, Qt::KeyboardModifiers modifiers, quint32 code, quint32 keysym, - const QString &text, bool autorepeat, quint32 timestamp, LibInput::Device *device) + const QString &text, bool autorepeat, quint32 timestamp, InputDevice *device) : QKeyEvent(type, key, modifiers, code, keysym, 0, text, autorepeat) , m_device(device) { setTimestamp(timestamp); } -SwitchEvent::SwitchEvent(State state, quint32 timestamp, quint64 timestampMicroseconds, LibInput::Device* device) +SwitchEvent::SwitchEvent(State state, quint32 timestamp, quint64 timestampMicroseconds, InputDevice* device) : QInputEvent(QEvent::User) , m_state(state) , m_timestampMicroseconds(timestampMicroseconds) diff --git a/src/input_event.h b/src/input_event.h index bbe01772c5..acf134b80e 100644 --- a/src/input_event.h +++ b/src/input_event.h @@ -16,10 +16,7 @@ namespace KWin { -namespace LibInput -{ -class Device; -} +class InputDevice; class MouseEvent : public QMouseEvent { @@ -27,7 +24,7 @@ public: explicit MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, quint32 timestamp, const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 timestampMicroseconds, - LibInput::Device *device); + InputDevice *device); QSizeF delta() const { return m_delta; @@ -41,7 +38,7 @@ public: return m_timestampMicroseconds; } - LibInput::Device *device() const { + InputDevice *device() const { return m_device; } @@ -65,7 +62,7 @@ private: QSizeF m_delta; QSizeF m_deltaUnccelerated; quint64 m_timestampMicroseconds; - LibInput::Device *m_device; + InputDevice *m_device; Qt::KeyboardModifiers m_modifiersRelevantForShortcuts = Qt::KeyboardModifiers(); quint32 m_nativeButton = 0; }; @@ -76,7 +73,7 @@ class WheelEvent : public QWheelEvent public: explicit WheelEvent(const QPointF &pos, qreal delta, qint32 discreteDelta, Qt::Orientation orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, InputRedirection::PointerAxisSource source, - quint32 timestamp, LibInput::Device *device); + quint32 timestamp, InputDevice *device); Qt::Orientation orientation() const { return m_orientation; @@ -94,7 +91,7 @@ public: return m_source; } - LibInput::Device *device() const { + InputDevice *device() const { return m_device; } @@ -107,7 +104,7 @@ public: } private: - LibInput::Device *m_device; + InputDevice *m_device; Qt::Orientation m_orientation; qreal m_delta; qint32 m_discreteDelta; @@ -119,9 +116,9 @@ class KeyEvent : public QKeyEvent { public: explicit KeyEvent(QEvent::Type type, Qt::Key key, Qt::KeyboardModifiers modifiers, quint32 code, quint32 keysym, - const QString &text, bool autorepeat, quint32 timestamp, LibInput::Device *device); + const QString &text, bool autorepeat, quint32 timestamp, InputDevice *device); - LibInput::Device *device() const { + InputDevice *device() const { return m_device; } @@ -134,7 +131,7 @@ public: } private: - LibInput::Device *m_device; + InputDevice *m_device; Qt::KeyboardModifiers m_modifiersRelevantForShortcuts = Qt::KeyboardModifiers(); }; @@ -145,7 +142,7 @@ public: Off, On }; - explicit SwitchEvent(State state, quint32 timestamp, quint64 timestampMicroseconds, LibInput::Device *device); + explicit SwitchEvent(State state, quint32 timestamp, quint64 timestampMicroseconds, InputDevice *device); State state() const { return m_state; @@ -155,14 +152,14 @@ public: return m_timestampMicroseconds; } - LibInput::Device *device() const { + InputDevice *device() const { return m_device; } private: State m_state; quint64 m_timestampMicroseconds; - LibInput::Device *m_device; + InputDevice *m_device; }; class TabletToolId diff --git a/src/inputbackend.cpp b/src/inputbackend.cpp new file mode 100644 index 0000000000..16e150bf6c --- /dev/null +++ b/src/inputbackend.cpp @@ -0,0 +1,27 @@ +/* + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "inputbackend.h" + +namespace KWin +{ + +InputBackend::InputBackend(QObject *parent) + : QObject(parent) +{ +} + +KSharedConfigPtr InputBackend::config() const +{ + return m_config; +} + +void InputBackend::setConfig(KSharedConfigPtr config) +{ + m_config = config; +} + +} // namespace KWin diff --git a/src/inputbackend.h b/src/inputbackend.h new file mode 100644 index 0000000000..ec51e8274d --- /dev/null +++ b/src/inputbackend.h @@ -0,0 +1,40 @@ +/* + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include "kwin_export.h" + +#include + +#include + +namespace KWin +{ + +class InputDevice; + +class KWIN_EXPORT InputBackend : public QObject +{ + Q_OBJECT + +public: + explicit InputBackend(QObject *parent = nullptr); + + KSharedConfigPtr config() const; + void setConfig(KSharedConfigPtr config); + + virtual void initialize() {} + +Q_SIGNALS: + void deviceAdded(InputDevice *device); + void deviceRemoved(InputDevice *device); + +private: + KSharedConfigPtr m_config; +}; + +} // namespace KWin diff --git a/src/inputdevice.cpp b/src/inputdevice.cpp new file mode 100644 index 0000000000..43ba9d4fb1 --- /dev/null +++ b/src/inputdevice.cpp @@ -0,0 +1,17 @@ +/* + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "inputdevice.h" + +namespace KWin +{ + +InputDevice::InputDevice(QObject *parent) + : QObject(parent) +{ +} + +} // namespace KWin diff --git a/src/inputdevice.h b/src/inputdevice.h new file mode 100644 index 0000000000..5d2bad2bff --- /dev/null +++ b/src/inputdevice.h @@ -0,0 +1,83 @@ +/* + SPDX-FileCopyrightText: 2016 Martin Gräßlin + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include "kwin_export.h" +#include "input.h" + +#include + +namespace KWin +{ + +/** + * The InputDevice class represents an input device, e.g. a mouse, or a keyboard, etc. + */ +class KWIN_EXPORT InputDevice : public QObject +{ + Q_OBJECT + +public: + explicit InputDevice(QObject *parent = nullptr); + + virtual QString sysName() const = 0; + virtual QString name() const = 0; + + virtual bool isEnabled() const = 0; + virtual void setEnabled(bool enabled) = 0; + + virtual LEDs leds() const = 0; + virtual void setLeds(LEDs leds) = 0; + + virtual bool isKeyboard() const = 0; + virtual bool isAlphaNumericKeyboard() const = 0; + virtual bool isPointer() const = 0; + virtual bool isTouchpad() const = 0; + virtual bool isTouch() const = 0; + virtual bool isTabletTool() const = 0; + virtual bool isTabletPad() const = 0; + virtual bool isTabletModeSwitch() const = 0; + virtual bool isLidSwitch() const = 0; + +Q_SIGNALS: + void keyChanged(quint32 key, InputRedirection::KeyboardKeyState, quint32 time, InputDevice *device); + void pointerButtonChanged(quint32 button, InputRedirection::PointerButtonState state, quint32 time, InputDevice *device); + void pointerMotionAbsolute(const QPointF &position, quint32 time, InputDevice *device); + void pointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint32 time, quint64 timeMicroseconds, InputDevice *device); + void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, + InputRedirection::PointerAxisSource source, quint32 time, InputDevice *device); + void touchFrame(InputDevice *device); + void touchCanceled(InputDevice *device); + void touchDown(qint32 id, const QPointF &absolutePos, quint32 time, InputDevice *device); + void touchUp(qint32 id, quint32 time, InputDevice *device); + void touchMotion(qint32 id, const QPointF &absolutePos, quint32 time, InputDevice *device); + void swipeGestureBegin(int fingerCount, quint32 time, InputDevice *device); + void swipeGestureUpdate(const QSizeF &delta, quint32 time, InputDevice *device); + void swipeGestureEnd(quint32 time, InputDevice *device); + void swipeGestureCancelled(quint32 time, InputDevice *device); + void pinchGestureBegin(int fingerCount, quint32 time, InputDevice *device); + void pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, InputDevice *device); + void pinchGestureEnd(quint32 time, InputDevice *device); + void pinchGestureCancelled(quint32 time, InputDevice *device); + void holdGestureBegin(int fingerCount, quint32 time, InputDevice *device); + void holdGestureEnd(quint32 time, InputDevice *device); + void holdGestureCancelled(quint32 time, InputDevice *device); + void switchToggledOn(quint32 time, quint64 timeMicroseconds, InputDevice *device); + void switchToggledOff(quint32 time, quint64 timeMicroseconds, InputDevice *device); + + void tabletToolEvent(InputRedirection::TabletEventType type, const QPointF &pos, + qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown, + bool tipNear, const TabletToolId &tabletToolId, quint32 time); + void tabletToolButtonEvent(uint button, bool isPressed, const TabletToolId &tabletToolId); + + void tabletPadButtonEvent(uint button, bool isPressed, const TabletPadId &tabletPadId); + void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); + void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); +}; + +} // namespace KWin diff --git a/src/keyboard_input.cpp b/src/keyboard_input.cpp index 77dff95e5d..fb22d72884 100644 --- a/src/keyboard_input.cpp +++ b/src/keyboard_input.cpp @@ -20,6 +20,7 @@ #include "workspace.h" // KWayland #include +#include #include //screenlocker #include @@ -103,6 +104,11 @@ void KeyboardInputRedirection::init() m_xkb->setNumLockConfig(InputConfig::self()->inputConfig()); m_xkb->setConfig(config); + // Workaround for QTBUG-54371: if there is no real keyboard Qt doesn't request virtual keyboard + waylandServer()->seat()->setHasKeyboard(true); + // connect(m_input, &InputRedirection::hasAlphaNumericKeyboardChanged, + // waylandServer()->seat(), &KWaylandServer::SeatInterface::setHasKeyboard); + m_input->installInputEventSpy(new KeyStateChangedSpy(m_input)); m_modifiersChangedSpy = new ModifiersChangedSpy(m_input); m_input->installInputEventSpy(m_modifiersChangedSpy); @@ -135,6 +141,23 @@ void KeyboardInputRedirection::init() if (waylandServer()->hasScreenLockerIntegration()) { connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &KeyboardInputRedirection::update); } + + reconfigure(); +} + +void KeyboardInputRedirection::reconfigure() +{ + if (waylandServer()->seat()->keyboard()) { + const auto config = InputConfig::self()->inputConfig()->group(QStringLiteral("Keyboard")); + const int delay = config.readEntry("RepeatDelay", 660); + const int rate = int(config.readEntry("RepeatRate", 25.0)); + const QString repeatMode = config.readEntry("KeyRepeat", "repeat"); + // when the clients will repeat the character or turn repeat key events into an accent character selection, we want + // to tell the clients that we are indeed repeating keys. + const bool enabled = repeatMode == QLatin1String("accent") || repeatMode == QLatin1String("repeat"); + + waylandServer()->seat()->keyboard()->setRepeatInfo(enabled ? rate : 0, delay); + } } void KeyboardInputRedirection::update() @@ -178,7 +201,7 @@ void KeyboardInputRedirection::update() } } -void KeyboardInputRedirection::processKey(uint32_t key, InputRedirection::KeyboardKeyState state, uint32_t time, LibInput::Device *device) +void KeyboardInputRedirection::processKey(uint32_t key, InputRedirection::KeyboardKeyState state, uint32_t time, InputDevice *device) { QEvent::Type type; bool autoRepeat = false; diff --git a/src/keyboard_input.h b/src/keyboard_input.h index 43f1e19176..f921c62a2d 100644 --- a/src/keyboard_input.h +++ b/src/keyboard_input.h @@ -32,16 +32,12 @@ typedef uint32_t xkb_layout_index_t; namespace KWin { +class InputDevice; class InputRedirection; class KeyboardLayout; class ModifiersChangedSpy; class Toplevel; -namespace LibInput -{ -class Device; -} - class KWIN_EXPORT KeyboardInputRedirection : public QObject { Q_OBJECT @@ -50,13 +46,14 @@ public: ~KeyboardInputRedirection() override; void init(); + void reconfigure(); void update(); /** * @internal */ - void processKey(uint32_t key, InputRedirection::KeyboardKeyState state, uint32_t time, LibInput::Device *device = nullptr); + void processKey(uint32_t key, InputRedirection::KeyboardKeyState state, uint32_t time, InputDevice *device = nullptr); /** * @internal */ diff --git a/src/libinput/connection.cpp b/src/libinput/connection.cpp index 46caeb3075..4772b7aecc 100644 --- a/src/libinput/connection.cpp +++ b/src/libinput/connection.cpp @@ -25,9 +25,7 @@ #include "udev.h" #include "libinput_logging.h" -#include #include -#include #include #include @@ -53,8 +51,12 @@ public: : QObject(con) , m_con(con) { - connect(con, &Connection::deviceAddedSysName, this, &ConnectionAdaptor::deviceAdded); - connect(con, &Connection::deviceRemovedSysName, this, &ConnectionAdaptor::deviceRemoved); + connect(con, &Connection::deviceAdded, this, [this](LibInput::Device *inputDevice) { + Q_EMIT deviceAdded(inputDevice->sysName()); + }); + connect(con, &Connection::deviceRemoved, this, [this](LibInput::Device *inputDevice) { + Q_EMIT deviceRemoved(inputDevice->sysName()); + }); QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/KWin/InputDevice"), QStringLiteral("org.kde.KWin.InputDeviceManager"), @@ -81,21 +83,6 @@ Connection *Connection::s_self = nullptr; static ConnectionAdaptor *s_adaptor = nullptr; static Context *s_context = nullptr; -static quint32 toLibinputLEDS(LEDs leds) -{ - quint32 libinputLeds = 0; - if (leds.testFlag(LED::NumLock)) { - libinputLeds = libinputLeds | LIBINPUT_LED_NUM_LOCK; - } - if (leds.testFlag(LED::CapsLock)) { - libinputLeds = libinputLeds | LIBINPUT_LED_CAPS_LOCK; - } - if (leds.testFlag(LED::ScrollLock)) { - libinputLeds = libinputLeds | LIBINPUT_LED_SCROLL_LOCK; - } - return libinputLeds; -} - Connection::Connection(QObject *parent) : Connection(nullptr, parent) { @@ -140,7 +127,6 @@ Connection::Connection(Context *input, QObject *parent) , m_input(input) , m_notifier(nullptr) , m_mutex(QMutex::Recursive) - , m_leds() { Q_ASSERT(m_input); // need to connect to KGlobalSettings as the mouse KCM does not emit a dedicated signal @@ -164,13 +150,6 @@ void Connection::setup() void Connection::doSetup() { - connect(s_self, &Connection::deviceAdded, s_self, [](Device* device) { - Q_EMIT s_self->deviceAddedSysName(device->sysName()); - }); - connect(s_self, &Connection::deviceRemoved, s_self, [](Device* device) { - Q_EMIT s_self->deviceRemovedSysName(device->sysName()); - }); - Q_ASSERT(!m_notifier); m_notifier = new QSocketNotifier(m_input->fileDescriptor(), QSocketNotifier::Read, this); connect(m_notifier, &QSocketNotifier::activated, this, &Connection::handleEvent); @@ -181,11 +160,11 @@ void Connection::doSetup() return; } m_input->resume(); - wasSuspended = true; } else { deactivate(); } }); + connect(kwinApp()->platform(), &Platform::screensQueried, this, &Connection::updateScreens); handleEvent(); } @@ -194,11 +173,6 @@ void Connection::deactivate() if (m_input->isSuspended()) { return; } - m_keyboardBeforeSuspend = hasKeyboard(); - m_alphaNumericKeyboardBeforeSuspend = hasAlphaNumericKeyboard(); - m_pointerBeforeSuspend = hasPointer(); - m_touchBeforeSuspend = hasTouch(); - m_tabletModeSwitchBeforeSuspend = hasTabletModeSwitch(); m_input->suspend(); handleEvent(); } @@ -315,42 +289,10 @@ void Connection::processEvents() auto device = new Device(event->nativeDevice()); device->moveToThread(thread()); m_devices << device; - if (device->isKeyboard()) { - m_keyboard++; - if (device->isAlphaNumericKeyboard()) { - m_alphaNumericKeyboard++; - if (m_alphaNumericKeyboard == 1) { - Q_EMIT hasAlphaNumericKeyboardChanged(true); - } - } - if (m_keyboard == 1) { - Q_EMIT hasKeyboardChanged(true); - } - } - if (device->isPointer()) { - m_pointer++; - if (m_pointer == 1) { - Q_EMIT hasPointerChanged(true); - } - } - if (device->isTouch()) { - m_touch++; - if (m_touch == 1) { - Q_EMIT hasTouchChanged(true); - } - } - if (device->isTabletModeSwitch()) { - m_tabletModeSwitch++; - if (m_tabletModeSwitch == 1) { - Q_EMIT hasTabletModeSwitchChanged(true); - } - } + applyDeviceConfig(device); applyScreenToDevice(device); - // enable possible leds - libinput_device_led_update(device->device(), static_cast(toLibinputLEDS(m_leds))); - Q_EMIT deviceAdded(device); break; } @@ -363,57 +305,26 @@ void Connection::processEvents() auto device = *it; m_devices.erase(it); Q_EMIT deviceRemoved(device); - - if (device->isKeyboard()) { - m_keyboard--; - if (device->isAlphaNumericKeyboard()) { - m_alphaNumericKeyboard--; - if (m_alphaNumericKeyboard == 0) { - Q_EMIT hasAlphaNumericKeyboardChanged(false); - } - } - if (m_keyboard == 0) { - Q_EMIT hasKeyboardChanged(false); - } - } - if (device->isPointer()) { - m_pointer--; - if (m_pointer == 0) { - Q_EMIT hasPointerChanged(false); - } - } - if (device->isTouch()) { - m_touch--; - if (m_touch == 0) { - Q_EMIT hasTouchChanged(false); - } - } - if (device->isTabletModeSwitch()) { - m_tabletModeSwitch--; - if (m_tabletModeSwitch == 0) { - Q_EMIT hasTabletModeSwitchChanged(false); - } - } device->deleteLater(); break; } case LIBINPUT_EVENT_KEYBOARD_KEY: { KeyEvent *ke = static_cast(event.data()); - Q_EMIT keyChanged(ke->key(), ke->state(), ke->time(), ke->device()); + Q_EMIT ke->device()->keyChanged(ke->key(), ke->state(), ke->time(), ke->device()); break; } case LIBINPUT_EVENT_POINTER_AXIS: { PointerEvent *pe = static_cast(event.data()); const auto axes = pe->axis(); for (const InputRedirection::PointerAxis &axis : axes) { - Q_EMIT pointerAxisChanged(axis, pe->axisValue(axis), pe->discreteAxisValue(axis), - pe->axisSource(), pe->time(), pe->device()); + Q_EMIT pe->device()->pointerAxisChanged(axis, pe->axisValue(axis), pe->discreteAxisValue(axis), + pe->axisSource(), pe->time(), pe->device()); } break; } case LIBINPUT_EVENT_POINTER_BUTTON: { PointerEvent *pe = static_cast(event.data()); - Q_EMIT pointerButtonChanged(pe->button(), pe->buttonState(), pe->time(), pe->device()); + Q_EMIT pe->device()->pointerButtonChanged(pe->button(), pe->buttonState(), pe->time(), pe->device()); break; } case LIBINPUT_EVENT_POINTER_MOTION: { @@ -435,12 +346,12 @@ void Connection::processEvents() break; } } - Q_EMIT pointerMotion(delta, deltaNonAccel, latestTime, latestTimeUsec, pe->device()); + Q_EMIT pe->device()->pointerMotion(delta, deltaNonAccel, latestTime, latestTimeUsec, pe->device()); break; } case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: { PointerEvent *pe = static_cast(event.data()); - Q_EMIT pointerMotionAbsolute(pe->absolutePos(m_size), pe->time(), pe->device()); + Q_EMIT pe->device()->pointerMotionAbsolute(pe->absolutePos(workspace()->geometry().size()), pe->time(), pe->device()); break; } case LIBINPUT_EVENT_TOUCH_DOWN: { @@ -450,13 +361,13 @@ void Connection::processEvents() const QPointF globalPos = devicePointToGlobalPosition(te->absolutePos(output->modeSize()), output); - Q_EMIT touchDown(te->id(), globalPos, te->time(), te->device()); + Q_EMIT te->device()->touchDown(te->id(), globalPos, te->time(), te->device()); break; #endif } case LIBINPUT_EVENT_TOUCH_UP: { TouchEvent *te = static_cast(event.data()); - Q_EMIT touchUp(te->id(), te->time(), te->device()); + Q_EMIT te->device()->touchUp(te->id(), te->time(), te->device()); break; } case LIBINPUT_EVENT_TOUCH_MOTION: { @@ -466,67 +377,67 @@ void Connection::processEvents() const QPointF globalPos = devicePointToGlobalPosition(te->absolutePos(output->modeSize()), output); - Q_EMIT touchMotion(te->id(), globalPos, te->time(), te->device()); + Q_EMIT te->device()->touchMotion(te->id(), globalPos, te->time(), te->device()); break; #endif } case LIBINPUT_EVENT_TOUCH_CANCEL: { - Q_EMIT touchCanceled(event->device()); + Q_EMIT event->device()->touchCanceled(event->device()); break; } case LIBINPUT_EVENT_TOUCH_FRAME: { - Q_EMIT touchFrame(event->device()); + Q_EMIT event->device()->touchFrame(event->device()); break; } case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: { PinchGestureEvent *pe = static_cast(event.data()); - Q_EMIT pinchGestureBegin(pe->fingerCount(), pe->time(), pe->device()); + Q_EMIT pe->device()->pinchGestureBegin(pe->fingerCount(), pe->time(), pe->device()); break; } case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: { PinchGestureEvent *pe = static_cast(event.data()); - Q_EMIT pinchGestureUpdate(pe->scale(), pe->angleDelta(), pe->delta(), pe->time(), pe->device()); + Q_EMIT pe->device()->pinchGestureUpdate(pe->scale(), pe->angleDelta(), pe->delta(), pe->time(), pe->device()); break; } case LIBINPUT_EVENT_GESTURE_PINCH_END: { PinchGestureEvent *pe = static_cast(event.data()); if (pe->isCancelled()) { - Q_EMIT pinchGestureCancelled(pe->time(), pe->device()); + Q_EMIT pe->device()->pinchGestureCancelled(pe->time(), pe->device()); } else { - Q_EMIT pinchGestureEnd(pe->time(), pe->device()); + Q_EMIT pe->device()->pinchGestureEnd(pe->time(), pe->device()); } break; } case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: { SwipeGestureEvent *se = static_cast(event.data()); - Q_EMIT swipeGestureBegin(se->fingerCount(), se->time(), se->device()); + Q_EMIT se->device()->swipeGestureBegin(se->fingerCount(), se->time(), se->device()); break; } case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: { SwipeGestureEvent *se = static_cast(event.data()); - Q_EMIT swipeGestureUpdate(se->delta(), se->time(), se->device()); + Q_EMIT se->device()->swipeGestureUpdate(se->delta(), se->time(), se->device()); break; } case LIBINPUT_EVENT_GESTURE_SWIPE_END: { SwipeGestureEvent *se = static_cast(event.data()); if (se->isCancelled()) { - Q_EMIT swipeGestureCancelled(se->time(), se->device()); + Q_EMIT se->device()->swipeGestureCancelled(se->time(), se->device()); } else { - Q_EMIT swipeGestureEnd(se->time(), se->device()); + Q_EMIT se->device()->swipeGestureEnd(se->time(), se->device()); } break; } case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN: { HoldGestureEvent *he = static_cast(event.data()); - Q_EMIT holdGestureBegin(he->fingerCount(), he->time(), he->device()); + Q_EMIT he->device()->holdGestureBegin(he->fingerCount(), he->time(), he->device()); break; } case LIBINPUT_EVENT_GESTURE_HOLD_END: { HoldGestureEvent *he = static_cast(event.data()); if (he->isCancelled()) { - Q_EMIT holdGestureCancelled(he->time(), he->device()); + Q_EMIT he->device()->holdGestureCancelled(he->time(), he->device()); } else { - Q_EMIT holdGestureEnd(he->time(), he->device()); + Q_EMIT he->device()->holdGestureEnd(he->time(), he->device()); } break; } @@ -534,10 +445,10 @@ void Connection::processEvents() SwitchEvent *se = static_cast(event.data()); switch (se->state()) { case SwitchEvent::State::Off: - Q_EMIT switchToggledOff(se->time(), se->timeMicroseconds(), se->device()); + Q_EMIT se->device()->switchToggledOff(se->time(), se->timeMicroseconds(), se->device()); break; case SwitchEvent::State::On: - Q_EMIT switchToggledOn(se->time(), se->timeMicroseconds(), se->device()); + Q_EMIT se->device()->switchToggledOn(se->time(), se->timeMicroseconds(), se->device()); break; default: Q_UNREACHABLE(); @@ -573,42 +484,42 @@ void Connection::processEvents() #else const QPointF globalPos; #endif - Q_EMIT tabletToolEvent(tabletEventType, - globalPos, tte->pressure(), - tte->xTilt(), tte->yTilt(), tte->rotation(), - tte->isTipDown(), tte->isNearby(), createTabletId(tte->tool(), event->device()->groupUserData()), tte->time()); + Q_EMIT event->device()->tabletToolEvent(tabletEventType, + globalPos, tte->pressure(), + tte->xTilt(), tte->yTilt(), tte->rotation(), + tte->isTipDown(), tte->isNearby(), createTabletId(tte->tool(), event->device()->groupUserData()), tte->time()); } break; } case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: { auto *tabletEvent = static_cast(event.data()); - Q_EMIT tabletToolButtonEvent(tabletEvent->buttonId(), - tabletEvent->isButtonPressed(), - createTabletId(tabletEvent->tool(), event->device()->groupUserData())); + Q_EMIT event->device()->tabletToolButtonEvent(tabletEvent->buttonId(), + tabletEvent->isButtonPressed(), + createTabletId(tabletEvent->tool(), event->device()->groupUserData())); break; } case LIBINPUT_EVENT_TABLET_PAD_BUTTON: { auto *tabletEvent = static_cast(event.data()); - Q_EMIT tabletPadButtonEvent(tabletEvent->buttonId(), - tabletEvent->isButtonPressed(), - { event->device()->groupUserData() }); + Q_EMIT event->device()->tabletPadButtonEvent(tabletEvent->buttonId(), + tabletEvent->isButtonPressed(), + { event->device()->groupUserData() }); break; } case LIBINPUT_EVENT_TABLET_PAD_RING: { auto *tabletEvent = static_cast(event.data()); tabletEvent->position(); - Q_EMIT tabletPadRingEvent(tabletEvent->number(), - tabletEvent->position(), - tabletEvent->source() == LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER, - { event->device()->groupUserData() }); + Q_EMIT event->device()->tabletPadRingEvent(tabletEvent->number(), + tabletEvent->position(), + tabletEvent->source() == LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER, + { event->device()->groupUserData() }); break; } case LIBINPUT_EVENT_TABLET_PAD_STRIP: { auto *tabletEvent = static_cast(event.data()); - Q_EMIT tabletPadStripEvent(tabletEvent->number(), - tabletEvent->position(), - tabletEvent->source() == LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER, - { event->device()->groupUserData() }); + Q_EMIT event->device()->tabletPadStripEvent(tabletEvent->number(), + tabletEvent->position(), + tabletEvent->source() == LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER, + { event->device()->groupUserData() }); break; } default: @@ -616,29 +527,6 @@ void Connection::processEvents() break; } } - if (wasSuspended) { - if (m_keyboardBeforeSuspend && !m_keyboard) { - Q_EMIT hasKeyboardChanged(false); - } - if (m_alphaNumericKeyboardBeforeSuspend && !m_alphaNumericKeyboard) { - Q_EMIT hasAlphaNumericKeyboardChanged(false); - } - if (m_pointerBeforeSuspend && !m_pointer) { - Q_EMIT hasPointerChanged(false); - } - if (m_touchBeforeSuspend && !m_touch) { - Q_EMIT hasTouchChanged(false); - } - if (m_tabletModeSwitchBeforeSuspend && !m_tabletModeSwitch) { - Q_EMIT hasTabletModeSwitchChanged(false); - } - wasSuspended = false; - } -} - -void Connection::setScreenSize(const QSize &size) -{ - m_size = size; } void Connection::updateScreens() @@ -718,14 +606,6 @@ void Connection::applyScreenToDevice(Device *device) #endif } -bool Connection::isSuspended() const -{ - if (!s_context) { - return false; - } - return s_context->isSuspended(); -} - void Connection::applyDeviceConfig(Device *device) { // pass configuration to Device @@ -745,63 +625,6 @@ void Connection::slotKGlobalSettingsNotifyChange(int type, int arg) } } -void Connection::toggleTouchpads() -{ - bool changed = false; - m_touchpadsEnabled = !m_touchpadsEnabled; - for (auto it = m_devices.constBegin(); it != m_devices.constEnd(); ++it) { - auto device = *it; - if (!device->isTouchpad()) { - continue; - } - const bool old = device->isEnabled(); - device->setEnabled(m_touchpadsEnabled); - if (old != device->isEnabled()) { - changed = true; - } - } - if (changed) { - // send OSD message - QDBusMessage msg = QDBusMessage::createMethodCall( - QStringLiteral("org.kde.plasmashell"), - QStringLiteral("/org/kde/osdService"), - QStringLiteral("org.kde.osdService"), - QStringLiteral("touchpadEnabledChanged") - ); - msg.setArguments({m_touchpadsEnabled}); - QDBusConnection::sessionBus().asyncCall(msg); - } -} - -void Connection::enableTouchpads() -{ - if (m_touchpadsEnabled) { - return; - } - toggleTouchpads(); -} - -void Connection::disableTouchpads() -{ - if (!m_touchpadsEnabled) { - return; - } - toggleTouchpads(); -} - -void Connection::updateLEDs(LEDs leds) -{ - if (m_leds == leds) { - return; - } - m_leds = leds; - // update on devices - const libinput_led l = static_cast(toLibinputLEDS(leds)); - for (auto it = m_devices.constBegin(), end = m_devices.constEnd(); it != end; ++it) { - libinput_device_led_update((*it)->device(), l); - } -} - QStringList Connection::devicesSysNames() const { QStringList sl; Q_FOREACH (Device *d, m_devices) { diff --git a/src/libinput/connection.h b/src/libinput/connection.h index 9fbf4b71f1..c5178cf4e1 100644 --- a/src/libinput/connection.h +++ b/src/libinput/connection.h @@ -11,7 +11,7 @@ #include -#include "input.h" +#include #include #include @@ -44,91 +44,15 @@ public: } void setup(); - /** - * Sets the screen @p size. This is needed for mapping absolute pointer events to - * the screen data. - */ - void setScreenSize(const QSize &size); - void updateScreens(); - - bool hasKeyboard() const { - return m_keyboard > 0; - } - bool hasAlphaNumericKeyboard() const { - return m_alphaNumericKeyboard > 0; - } - bool hasTouch() const { - return m_touch > 0; - } - bool hasPointer() const { - return m_pointer > 0; - } - bool hasTabletModeSwitch() const { - return m_tabletModeSwitch > 0; - } - - bool isSuspended() const; - void deactivate(); - void processEvents(); - void toggleTouchpads(); - void enableTouchpads(); - void disableTouchpads(); - - QVector devices() const { - return m_devices; - } - QStringList devicesSysNames() const; - void updateLEDs(KWin::LEDs leds); - Q_SIGNALS: - void keyChanged(quint32 key, KWin::InputRedirection::KeyboardKeyState, quint32 time, KWin::LibInput::Device *device); - void pointerButtonChanged(quint32 button, KWin::InputRedirection::PointerButtonState state, quint32 time, KWin::LibInput::Device *device); - void pointerMotionAbsolute(const QPointF &position, quint32 time, KWin::LibInput::Device *device); - void pointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint32 time, quint64 timeMicroseconds, KWin::LibInput::Device *device); - void pointerAxisChanged(KWin::InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, - KWin::InputRedirection::PointerAxisSource source, quint32 time, KWin::LibInput::Device *device); - void touchFrame(KWin::LibInput::Device *device); - void touchCanceled(KWin::LibInput::Device *device); - void touchDown(qint32 id, const QPointF &absolutePos, quint32 time, KWin::LibInput::Device *device); - void touchUp(qint32 id, quint32 time, KWin::LibInput::Device *device); - void touchMotion(qint32 id, const QPointF &absolutePos, quint32 time, KWin::LibInput::Device *device); - void hasKeyboardChanged(bool); - void hasAlphaNumericKeyboardChanged(bool); - void hasPointerChanged(bool); - void hasTouchChanged(bool); - void hasTabletModeSwitchChanged(bool); void deviceAdded(KWin::LibInput::Device *); void deviceRemoved(KWin::LibInput::Device *); - void deviceAddedSysName(QString); - void deviceRemovedSysName(QString); - void swipeGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device); - void swipeGestureUpdate(const QSizeF &delta, quint32 time, KWin::LibInput::Device *device); - void swipeGestureEnd(quint32 time, KWin::LibInput::Device *device); - void swipeGestureCancelled(quint32 time, KWin::LibInput::Device *device); - void pinchGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device); - void pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, KWin::LibInput::Device *device); - void pinchGestureEnd(quint32 time, KWin::LibInput::Device *device); - void pinchGestureCancelled(quint32 time, KWin::LibInput::Device *device); - void holdGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device); - void holdGestureEnd(quint32 time, KWin::LibInput::Device *device); - void holdGestureCancelled(quint32 time, KWin::LibInput::Device *device); - void switchToggledOn(quint32 time, quint64 timeMicroseconds, KWin::LibInput::Device *device); - void switchToggledOff(quint32 time, quint64 timeMicroseconds, KWin::LibInput::Device *device); - - void tabletToolEvent(KWin::InputRedirection::TabletEventType type, const QPointF &pos, - qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown, - bool tipNear, const TabletToolId &tabletToolId, quint32 time); - void tabletToolButtonEvent(uint button, bool isPressed, const TabletToolId &tabletToolId); - - void tabletPadButtonEvent(uint button, bool isPressed, const TabletPadId &tabletPadId); - void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); - void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); void eventsRead(); @@ -143,24 +67,10 @@ private: void applyScreenToDevice(Device *device); Context *m_input; QSocketNotifier *m_notifier; - QSize m_size; - int m_keyboard = 0; - int m_alphaNumericKeyboard = 0; - int m_pointer = 0; - int m_touch = 0; - int m_tabletModeSwitch = 0; - bool m_keyboardBeforeSuspend = false; - bool m_alphaNumericKeyboardBeforeSuspend = false; - bool m_pointerBeforeSuspend = false; - bool m_touchBeforeSuspend = false; - bool m_tabletModeSwitchBeforeSuspend = false; QMutex m_mutex; QVector m_eventQueue; - bool wasSuspended = false; QVector m_devices; KSharedConfigPtr m_config; - bool m_touchpadsEnabled = true; - LEDs m_leds; KWIN_SINGLETON(Connection) }; diff --git a/src/libinput/device.cpp b/src/libinput/device.cpp index b2fd5c0e16..38b5597845 100644 --- a/src/libinput/device.cpp +++ b/src/libinput/device.cpp @@ -152,7 +152,7 @@ QMatrix4x4 defaultCalibrationMatrix(libinput_device *device) } Device::Device(libinput_device *device, QObject *parent) - : QObject(parent) + : InputDevice(parent) , m_device(device) , m_keyboard(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_KEYBOARD)) , m_pointer(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_POINTER)) @@ -555,5 +555,33 @@ void Device::setOutput(AbstractOutput *output) m_output = output; } +static libinput_led toLibinputLEDS(LEDs leds) +{ + quint32 libinputLeds = 0; + if (leds.testFlag(LED::NumLock)) { + libinputLeds = libinputLeds | LIBINPUT_LED_NUM_LOCK; + } + if (leds.testFlag(LED::CapsLock)) { + libinputLeds = libinputLeds | LIBINPUT_LED_CAPS_LOCK; + } + if (leds.testFlag(LED::ScrollLock)) { + libinputLeds = libinputLeds | LIBINPUT_LED_SCROLL_LOCK; + } + return libinput_led(libinputLeds); +} + +LEDs Device::leds() const +{ + return m_leds; +} + +void Device::setLeds(LEDs leds) +{ + if (m_leds != leds) { + m_leds = leds; + libinput_device_led_update(m_device, toLibinputLEDS(m_leds)); + } +} + } } diff --git a/src/libinput/device.h b/src/libinput/device.h index 6dad013b9b..1d6b4b5aa7 100644 --- a/src/libinput/device.h +++ b/src/libinput/device.h @@ -9,6 +9,8 @@ #ifndef KWIN_LIBINPUT_DEVICE_H #define KWIN_LIBINPUT_DEVICE_H +#include "inputdevice.h" + #include #include @@ -18,7 +20,6 @@ #include #include #include -#include "kwin_export.h" struct libinput_device; @@ -30,7 +31,7 @@ namespace LibInput { enum class ConfigKey; -class KWIN_EXPORT Device : public QObject +class KWIN_EXPORT Device : public InputDevice { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.InputDevice") @@ -137,16 +138,16 @@ public: explicit Device(libinput_device *device, QObject *parent = nullptr); ~Device() override; - bool isKeyboard() const { + bool isKeyboard() const override { return m_keyboard; } - bool isAlphaNumericKeyboard() const { + bool isAlphaNumericKeyboard() const override { return m_alphaNumericKeyboard; } - bool isPointer() const { + bool isPointer() const override { return m_pointer; } - bool isTouchpad() const{ + bool isTouchpad() const override { return m_pointer && // ignore all combined devices. E.g. a touchpad on a keyboard we don't want to toggle // as that would result in the keyboard going off as well @@ -154,22 +155,22 @@ public: // is this a touch pad? We don't really know, let's do some assumptions (m_tapFingerCount > 0 || m_supportsDisableWhileTyping || m_supportsDisableEventsOnExternalMouse); } - bool isTouch() const { + bool isTouch() const override { return m_touch; } - bool isTabletTool() const { + bool isTabletTool() const override { return m_tabletTool; } - bool isTabletPad() const { + bool isTabletPad() const override { return m_tabletPad; } bool supportsGesture() const { return m_supportsGesture; } - QString name() const { + QString name() const override { return m_name; } - QString sysName() const { + QString sysName() const override { return m_sysName; } QString outputName() const { @@ -424,10 +425,10 @@ public: return (quint32) m_defaultClickMethod; } - bool isEnabled() const { + bool isEnabled() const override { return m_enabled; } - void setEnabled(bool enabled); + void setEnabled(bool enabled) override; libinput_device *device() const { return m_device; @@ -452,11 +453,11 @@ public: return m_switch; } - bool isLidSwitch() const { + bool isLidSwitch() const override { return m_lidSwitch; } - bool isTabletModeSwitch() const { + bool isTabletModeSwitch() const override { return m_tabletSwitch; } @@ -468,6 +469,9 @@ public: AbstractOutput *output() const; void setOutput(AbstractOutput *output); + LEDs leds() const override; + void setLeds(LEDs leds) override; + /** * All created Devices */ @@ -569,6 +573,7 @@ private: enum libinput_config_click_method m_defaultClickMethod; enum libinput_config_click_method m_clickMethod; + LEDs m_leds; static QVector s_devices; }; diff --git a/src/libinput/libinputbackend.cpp b/src/libinput/libinputbackend.cpp new file mode 100644 index 0000000000..aacc849741 --- /dev/null +++ b/src/libinput/libinputbackend.cpp @@ -0,0 +1,51 @@ +/* + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "libinputbackend.h" +#include "connection.h" +#include "device.h" + +namespace KWin +{ + +LibinputBackend::LibinputBackend(QObject *parent) + : InputBackend(parent) +{ + m_thread = new QThread(); + m_thread->setObjectName(QStringLiteral("libinput-connection")); + m_thread->start(); + + m_connection = LibInput::Connection::create(this); + m_connection->moveToThread(m_thread); + + connect(m_connection, &LibInput::Connection::eventsRead, this, [this]() { + m_connection->processEvents(); + }, Qt::QueuedConnection); + + // Direct connection because the deviceAdded() and the deviceRemoved() signals are emitted + // from the main thread. + connect(m_connection, &LibInput::Connection::deviceAdded, + this, &InputBackend::deviceAdded, Qt::DirectConnection); + connect(m_connection, &LibInput::Connection::deviceRemoved, + this, &InputBackend::deviceRemoved, Qt::DirectConnection); +} + +LibinputBackend::~LibinputBackend() +{ + m_connection->deleteLater(); + + m_thread->quit(); + m_thread->wait(); + delete m_thread; +} + +void LibinputBackend::initialize() +{ + m_connection->setInputConfig(config()); + m_connection->setup(); +} + +} // namespace KWin diff --git a/src/libinput/libinputbackend.h b/src/libinput/libinputbackend.h new file mode 100644 index 0000000000..7f8f2d05e6 --- /dev/null +++ b/src/libinput/libinputbackend.h @@ -0,0 +1,36 @@ +/* + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include "inputbackend.h" + +#include + +namespace KWin +{ + +namespace LibInput +{ +class Connection; +} + +class KWIN_EXPORT LibinputBackend : public InputBackend +{ + Q_OBJECT + +public: + explicit LibinputBackend(QObject *parent = nullptr); + ~LibinputBackend() override; + + void initialize() override; + +private: + QThread *m_thread = nullptr; + LibInput::Connection *m_connection = nullptr; +}; + +} // namespace KWin diff --git a/src/main.cpp b/src/main.cpp index 3899226339..378dc98b34 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -579,18 +579,6 @@ bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag return false; } -static bool s_useLibinput = false; - -void Application::setUseLibinput(bool use) -{ - s_useLibinput = use; -} - -bool Application::usesLibinput() -{ - return s_useLibinput; -} - QProcessEnvironment Application::processStartupEnvironment() const { return QProcessEnvironment::systemEnvironment(); @@ -603,17 +591,6 @@ void Application::initPlatform(const KPluginMetaData &plugin) m_platform = qobject_cast(loader.instance()); if (m_platform) { m_platform->setParent(this); - // check whether it needs libinput - const QJsonObject &metaData = plugin.rawData(); - auto it = metaData.find(QStringLiteral("input")); - if (it != metaData.end()) { - if ((*it).isBool()) { - if (!(*it).toBool()) { - qCDebug(KWIN_CORE) << "Platform does not support input, enforcing libinput support"; - setUseLibinput(true); - } - } - } Q_EMIT platformCreated(); } else { qCWarning(KWIN_CORE) << "Could not create plugin" << plugin.name() << "error:" << loader.errorString(); diff --git a/src/main.h b/src/main.h index 50dfc9c8cf..5c1440d3fc 100644 --- a/src/main.h +++ b/src/main.h @@ -207,9 +207,6 @@ public: static void setupMalloc(); static void setupLocalizedString(); - static bool usesLibinput(); - static void setUseLibinput(bool use); - Q_SIGNALS: void x11ConnectionChanged(); void x11ConnectionAboutToBeDestroyed(); diff --git a/src/main_wayland.cpp b/src/main_wayland.cpp index eb013810d7..3e88de30d0 100644 --- a/src/main_wayland.cpp +++ b/src/main_wayland.cpp @@ -509,9 +509,6 @@ int main(int argc, char * argv[]) if (hasOutputCountOption) { parser.addOption(outputCountOption); } - QCommandLineOption libinputOption(QStringLiteral("libinput"), - i18n("Enable libinput support for input events processing. Note: never use in a nested session. (deprecated)")); - parser.addOption(libinputOption); QCommandLineOption drmOption(QStringLiteral("drm"), i18n("Render through drm node.")); if (hasDrmOption) { parser.addOption(drmOption); @@ -579,8 +576,6 @@ int main(int argc, char * argv[]) a.setSessionArgument(parser.value(exitWithSessionOption)); } - KWin::Application::setUseLibinput(parser.isSet(libinputOption)); - QString pluginName; QSize initialWindowSize; QByteArray deviceIdentifier; diff --git a/src/platform.cpp b/src/platform.cpp index e96bb69d69..9f43fe3186 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -76,6 +76,11 @@ void Platform::doShowCursor() { } +InputBackend *Platform::createInputBackend() +{ + return nullptr; +} + OpenGLBackend *Platform::createOpenGLBackend() { return nullptr; diff --git a/src/platform.h b/src/platform.h index a4f95428f8..b2e0c51a03 100644 --- a/src/platform.h +++ b/src/platform.h @@ -31,6 +31,7 @@ class AbstractOutput; class Edge; class Compositor; class DmaBufTexture; +class InputBackend; class OverlayWindow; class OpenGLBackend; class Outline; @@ -61,6 +62,7 @@ public: virtual Session *session() const = 0; virtual bool initialize() = 0; + virtual InputBackend *createInputBackend(); virtual OpenGLBackend *createOpenGLBackend(); virtual QPainterBackend *createQPainterBackend(); virtual DmaBufTexture *createDmaBufTexture(const QSize &size) { diff --git a/src/plugins/platforms/drm/drm.json b/src/plugins/platforms/drm/drm.json index 373b63f152..9a278ce6f5 100644 --- a/src/plugins/platforms/drm/drm.json +++ b/src/plugins/platforms/drm/drm.json @@ -86,6 +86,5 @@ "Name[x-test]": "xxdrmxx", "Name[zh_CN]": "drm", "Name[zh_TW]": "drm" - }, - "input": false + } } diff --git a/src/plugins/platforms/drm/drm_backend.cpp b/src/plugins/platforms/drm/drm_backend.cpp index 8fb3669268..737090d88b 100644 --- a/src/plugins/platforms/drm/drm_backend.cpp +++ b/src/plugins/platforms/drm/drm_backend.cpp @@ -14,13 +14,13 @@ #include "drm_object_plane.h" #include "composite.h" #include "cursor.h" +#include "libinput/libinputbackend.h" #include "logging.h" #include "main.h" #include "renderloop.h" #include "scene_qpainter_drm_backend.h" #include "session.h" #include "udev.h" -#include "wayland_server.h" #include "drm_gpu.h" #include "egl_multi_backend.h" #include "drm_pipeline.h" @@ -33,8 +33,6 @@ #if HAVE_EGL_STREAMS #include "egl_stream_backend.h" #endif -// KWayland -#include // KF5 #include #include @@ -69,6 +67,7 @@ DrmBackend::DrmBackend(QObject *parent) , m_explicitGpus(qEnvironmentVariable("KWIN_DRM_DEVICES").split(':', Qt::SkipEmptyParts)) , m_dpmsFilter() { + setSupportsPointerWarping(true); setSupportsGammaControl(true); setPerScreenRenderingEnabled(true); supportsOutputChanges(); @@ -528,21 +527,6 @@ void DrmBackend::initCursor() setSoftwareCursorForced(needsSoftwareCursor); #endif - if (waylandServer()->seat()->hasPointer()) { - // The cursor is visible by default, do nothing. - } else { - hideCursor(); - } - - connect(waylandServer()->seat(), &KWaylandServer::SeatInterface::hasPointerChanged, this, - [this] { - if (waylandServer()->seat()->hasPointer()) { - showCursor(); - } else { - hideCursor(); - } - } - ); // now we have screens and can set cursors, so start tracking connect(Cursors::self(), &Cursors::currentCursorChanged, this, &DrmBackend::updateCursor); connect(Cursors::self(), &Cursors::positionChanged, this, &DrmBackend::moveCursor); @@ -621,6 +605,11 @@ void DrmBackend::moveCursor() } } +InputBackend *DrmBackend::createInputBackend() +{ + return new LibinputBackend(); +} + QPainterBackend *DrmBackend::createQPainterBackend() { return new DrmQPainterBackend(this, m_gpus.at(0)); diff --git a/src/plugins/platforms/drm/drm_backend.h b/src/plugins/platforms/drm/drm_backend.h index f4578cabd1..f06b973ea9 100644 --- a/src/plugins/platforms/drm/drm_backend.h +++ b/src/plugins/platforms/drm/drm_backend.h @@ -39,6 +39,7 @@ public: explicit DrmBackend(QObject *parent = nullptr); ~DrmBackend() override; + InputBackend *createInputBackend() override; QPainterBackend *createQPainterBackend() override; OpenGLBackend* createOpenGLBackend() override; DmaBufTexture *createDmaBufTexture(const QSize &size) override; diff --git a/src/plugins/platforms/fbdev/fb_backend.cpp b/src/plugins/platforms/fbdev/fb_backend.cpp index c38193b3c2..172ce569ea 100644 --- a/src/plugins/platforms/fbdev/fb_backend.cpp +++ b/src/plugins/platforms/fbdev/fb_backend.cpp @@ -9,6 +9,7 @@ #include "fb_backend.h" #include "composite.h" +#include "libinput/libinputbackend.h" #include "logging.h" #include "main.h" #include "platform.h" @@ -79,6 +80,7 @@ FramebufferBackend::FramebufferBackend(QObject *parent) , m_session(Session::create(this)) { setPerScreenRenderingEnabled(true); + setSupportsPointerWarping(true); } FramebufferBackend::~FramebufferBackend() @@ -89,6 +91,11 @@ FramebufferBackend::~FramebufferBackend() } } +InputBackend *FramebufferBackend::createInputBackend() +{ + return new LibinputBackend(this); +} + QPainterBackend *FramebufferBackend::createQPainterBackend() { return new FramebufferQPainterBackend(this); diff --git a/src/plugins/platforms/fbdev/fb_backend.h b/src/plugins/platforms/fbdev/fb_backend.h index 63a36416a8..497c422f2c 100644 --- a/src/plugins/platforms/fbdev/fb_backend.h +++ b/src/plugins/platforms/fbdev/fb_backend.h @@ -50,6 +50,7 @@ public: explicit FramebufferBackend(QObject *parent = nullptr); ~FramebufferBackend() override; + InputBackend *createInputBackend() override; QPainterBackend *createQPainterBackend() override; QSize screenSize() const override; diff --git a/src/plugins/platforms/fbdev/fbdev.json b/src/plugins/platforms/fbdev/fbdev.json index 4e3e1633dc..c23e188304 100644 --- a/src/plugins/platforms/fbdev/fbdev.json +++ b/src/plugins/platforms/fbdev/fbdev.json @@ -86,6 +86,5 @@ "Name[x-test]": "xxframebufferxx", "Name[zh_CN]": "framebuffer", "Name[zh_TW]": "framebuffer" - }, - "input": false + } } diff --git a/src/plugins/platforms/virtual/virtual.json b/src/plugins/platforms/virtual/virtual.json index 0ebe19c667..26401675c2 100644 --- a/src/plugins/platforms/virtual/virtual.json +++ b/src/plugins/platforms/virtual/virtual.json @@ -86,6 +86,5 @@ "Name[x-test]": "xxvirtualxx", "Name[zh_CN]": "virtual", "Name[zh_TW]": "虛擬" - }, - "input": true + } } diff --git a/src/plugins/platforms/wayland/wayland.json b/src/plugins/platforms/wayland/wayland.json index 51fb6156f9..a01f95ba04 100644 --- a/src/plugins/platforms/wayland/wayland.json +++ b/src/plugins/platforms/wayland/wayland.json @@ -84,6 +84,5 @@ "Name[x-test]": "xxwaylandxx", "Name[zh_CN]": "wayland", "Name[zh_TW]": "wayland" - }, - "input": true + } } diff --git a/src/plugins/platforms/wayland/wayland_backend.cpp b/src/plugins/platforms/wayland/wayland_backend.cpp index be5db29a26..d51cd22fd2 100644 --- a/src/plugins/platforms/wayland/wayland_backend.cpp +++ b/src/plugins/platforms/wayland/wayland_backend.cpp @@ -515,9 +515,6 @@ bool WaylandBackend::initialize() ); connect(m_registry, &Registry::seatAnnounced, this, [this](quint32 name) { - if (Application::usesLibinput()) { - return; - } m_seat = new WaylandSeat(m_registry->bindSeat(name, 2), this); } ); diff --git a/src/plugins/platforms/x11/standalone/x11.json b/src/plugins/platforms/x11/standalone/x11.json index 6b5855dafd..555439b436 100644 --- a/src/plugins/platforms/x11/standalone/x11.json +++ b/src/plugins/platforms/x11/standalone/x11.json @@ -83,6 +83,5 @@ "Name[x-test]": "xxx11-standalonexx", "Name[zh_CN]": "x11-standalone", "Name[zh_TW]": "x11-standalone" - }, - "input": true + } } diff --git a/src/plugins/platforms/x11/windowed/x11.json b/src/plugins/platforms/x11/windowed/x11.json index d96a39f7d3..f1c09d25b6 100644 --- a/src/plugins/platforms/x11/windowed/x11.json +++ b/src/plugins/platforms/x11/windowed/x11.json @@ -84,6 +84,5 @@ "Name[x-test]": "xxx11xx", "Name[zh_CN]": "x11", "Name[zh_TW]": "x11" - }, - "input": true + } } diff --git a/src/pointer_input.cpp b/src/pointer_input.cpp index c3c502dbf5..694a81c2c1 100644 --- a/src/pointer_input.cpp +++ b/src/pointer_input.cpp @@ -104,7 +104,6 @@ static QPointF confineToBoundingBox(const QPointF &pos, const QRectF &boundingBo PointerInputRedirection::PointerInputRedirection(InputRedirection* parent) : InputDeviceHandler(parent) , m_cursor(nullptr) - , m_supportsWarping(Application::usesLibinput()) { } @@ -113,10 +112,25 @@ PointerInputRedirection::~PointerInputRedirection() = default; void PointerInputRedirection::init() { Q_ASSERT(!inited()); + waylandServer()->seat()->setHasPointer(input()->hasPointer()); + connect(input(), &InputRedirection::hasPointerChanged, + waylandServer()->seat(), &KWaylandServer::SeatInterface::setHasPointer); + m_cursor = new CursorImage(this); setInited(true); InputDeviceHandler::init(); + if (!input()->hasPointer()) { + kwinApp()->platform()->hideCursor(); + } + connect(input(), &InputRedirection::hasPointerChanged, this, [this]() { + if (input()->hasPointer()) { + kwinApp()->platform()->showCursor(); + } else { + kwinApp()->platform()->hideCursor(); + } + }); + connect(m_cursor, &CursorImage::changed, Cursors::self()->mouse(), [this] { auto cursor = Cursors::self()->mouse(); cursor->updateCursor(m_cursor->image(), m_cursor->hotSpot()); @@ -242,17 +256,17 @@ private: int PositionUpdateBlocker::s_counter = 0; QVector PositionUpdateBlocker::s_scheduledPositions; -void PointerInputRedirection::processMotionAbsolute(const QPointF &pos, uint32_t time, LibInput::Device *device) +void PointerInputRedirection::processMotionAbsolute(const QPointF &pos, uint32_t time, InputDevice *device) { processMotionInternal(pos, QSizeF(), QSizeF(), time, 0, device); } -void PointerInputRedirection::processMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device) +void PointerInputRedirection::processMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, InputDevice *device) { processMotionInternal(m_pos + QPointF(delta.width(), delta.height()), delta, deltaNonAccelerated, time, timeUsec, device); } -void PointerInputRedirection::processMotionInternal(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device) +void PointerInputRedirection::processMotionInternal(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, InputDevice *device) { m_lastEventTime = time; if (!inited()) { @@ -275,7 +289,7 @@ void PointerInputRedirection::processMotionInternal(const QPointF &pos, const QS input()->processFilters(std::bind(&InputEventFilter::pointerEvent, std::placeholders::_1, &event, 0)); } -void PointerInputRedirection::processButton(uint32_t button, InputRedirection::PointerButtonState state, uint32_t time, LibInput::Device *device) +void PointerInputRedirection::processButton(uint32_t button, InputRedirection::PointerButtonState state, uint32_t time, InputDevice *device) { m_lastEventTime = time; QEvent::Type type; @@ -313,7 +327,7 @@ void PointerInputRedirection::processButton(uint32_t button, InputRedirection::P } void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, - InputRedirection::PointerAxisSource source, uint32_t time, LibInput::Device *device) + InputRedirection::PointerAxisSource source, uint32_t time, InputDevice *device) { m_lastEventTime = time; update(); @@ -333,7 +347,7 @@ void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qr input()->processFilters(std::bind(&InputEventFilter::wheelEvent, std::placeholders::_1, &wheelEvent)); } -void PointerInputRedirection::processSwipeGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processSwipeGestureBegin(int fingerCount, quint32 time, KWin::InputDevice *device) { m_lastEventTime = time; Q_UNUSED(device) @@ -345,7 +359,7 @@ void PointerInputRedirection::processSwipeGestureBegin(int fingerCount, quint32 input()->processFilters(std::bind(&InputEventFilter::swipeGestureBegin, std::placeholders::_1, fingerCount, time)); } -void PointerInputRedirection::processSwipeGestureUpdate(const QSizeF &delta, quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processSwipeGestureUpdate(const QSizeF &delta, quint32 time, KWin::InputDevice *device) { m_lastEventTime = time; Q_UNUSED(device) @@ -358,7 +372,7 @@ void PointerInputRedirection::processSwipeGestureUpdate(const QSizeF &delta, qui input()->processFilters(std::bind(&InputEventFilter::swipeGestureUpdate, std::placeholders::_1, delta, time)); } -void PointerInputRedirection::processSwipeGestureEnd(quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processSwipeGestureEnd(quint32 time, KWin::InputDevice *device) { m_lastEventTime = time; Q_UNUSED(device) @@ -371,7 +385,7 @@ void PointerInputRedirection::processSwipeGestureEnd(quint32 time, KWin::LibInpu input()->processFilters(std::bind(&InputEventFilter::swipeGestureEnd, std::placeholders::_1, time)); } -void PointerInputRedirection::processSwipeGestureCancelled(quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processSwipeGestureCancelled(quint32 time, KWin::InputDevice *device) { m_lastEventTime = time; Q_UNUSED(device) @@ -384,7 +398,7 @@ void PointerInputRedirection::processSwipeGestureCancelled(quint32 time, KWin::L input()->processFilters(std::bind(&InputEventFilter::swipeGestureCancelled, std::placeholders::_1, time)); } -void PointerInputRedirection::processPinchGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processPinchGestureBegin(int fingerCount, quint32 time, KWin::InputDevice *device) { m_lastEventTime = time; Q_UNUSED(device) @@ -397,7 +411,7 @@ void PointerInputRedirection::processPinchGestureBegin(int fingerCount, quint32 input()->processFilters(std::bind(&InputEventFilter::pinchGestureBegin, std::placeholders::_1, fingerCount, time)); } -void PointerInputRedirection::processPinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processPinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, KWin::InputDevice *device) { m_lastEventTime = time; Q_UNUSED(device) @@ -410,7 +424,7 @@ void PointerInputRedirection::processPinchGestureUpdate(qreal scale, qreal angle input()->processFilters(std::bind(&InputEventFilter::pinchGestureUpdate, std::placeholders::_1, scale, angleDelta, delta, time)); } -void PointerInputRedirection::processPinchGestureEnd(quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processPinchGestureEnd(quint32 time, KWin::InputDevice *device) { m_lastEventTime = time; Q_UNUSED(device) @@ -423,7 +437,7 @@ void PointerInputRedirection::processPinchGestureEnd(quint32 time, KWin::LibInpu input()->processFilters(std::bind(&InputEventFilter::pinchGestureEnd, std::placeholders::_1, time)); } -void PointerInputRedirection::processPinchGestureCancelled(quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processPinchGestureCancelled(quint32 time, KWin::InputDevice *device) { m_lastEventTime = time; Q_UNUSED(device) @@ -436,7 +450,7 @@ void PointerInputRedirection::processPinchGestureCancelled(quint32 time, KWin::L input()->processFilters(std::bind(&InputEventFilter::pinchGestureCancelled, std::placeholders::_1, time)); } -void PointerInputRedirection::processHoldGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processHoldGestureBegin(int fingerCount, quint32 time, KWin::InputDevice *device) { Q_UNUSED(device) if (!inited()) { @@ -448,7 +462,7 @@ void PointerInputRedirection::processHoldGestureBegin(int fingerCount, quint32 t input()->processFilters(std::bind(&InputEventFilter::holdGestureBegin, std::placeholders::_1, fingerCount, time)); } -void PointerInputRedirection::processHoldGestureEnd(quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processHoldGestureEnd(quint32 time, KWin::InputDevice *device) { Q_UNUSED(device) if (!inited()) { @@ -460,7 +474,7 @@ void PointerInputRedirection::processHoldGestureEnd(quint32 time, KWin::LibInput input()->processFilters(std::bind(&InputEventFilter::holdGestureEnd, std::placeholders::_1, time)); } -void PointerInputRedirection::processHoldGestureCancelled(quint32 time, KWin::LibInput::Device *device) +void PointerInputRedirection::processHoldGestureCancelled(quint32 time, KWin::InputDevice *device) { Q_UNUSED(device) if (!inited()) { @@ -946,13 +960,7 @@ bool PointerInputRedirection::supportsWarping() const if (!inited()) { return false; } - if (m_supportsWarping) { - return true; - } - if (kwinApp()->platform()->supportsPointerWarping()) { - return true; - } - return false; + return kwinApp()->platform()->supportsPointerWarping(); } void PointerInputRedirection::updateAfterScreenChange() diff --git a/src/pointer_input.h b/src/pointer_input.h index 109846c746..c432d6541e 100644 --- a/src/pointer_input.h +++ b/src/pointer_input.h @@ -30,6 +30,7 @@ class SurfaceInterface; namespace KWin { class CursorImage; +class InputDevice; class InputRedirection; class Toplevel; class CursorShape; @@ -39,11 +40,6 @@ namespace Decoration class DecoratedClientImpl; } -namespace LibInput -{ -class Device; -} - uint32_t qtMouseButtonToButton(Qt::MouseButton button); class KWIN_EXPORT PointerInputRedirection : public InputDeviceHandler @@ -86,66 +82,66 @@ public: /** * @internal */ - void processMotionAbsolute(const QPointF &pos, uint32_t time, LibInput::Device *device = nullptr); + void processMotionAbsolute(const QPointF &pos, uint32_t time, InputDevice *device = nullptr); /** * @internal */ - void processMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device); + void processMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, InputDevice *device); /** * @internal */ - void processButton(uint32_t button, InputRedirection::PointerButtonState state, uint32_t time, LibInput::Device *device = nullptr); + void processButton(uint32_t button, InputRedirection::PointerButtonState state, uint32_t time, InputDevice *device = nullptr); /** * @internal */ - void processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, InputRedirection::PointerAxisSource source, uint32_t time, LibInput::Device *device = nullptr); + void processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, InputRedirection::PointerAxisSource source, uint32_t time, InputDevice *device = nullptr); /** * @internal */ - void processSwipeGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device = nullptr); + void processSwipeGestureBegin(int fingerCount, quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processSwipeGestureUpdate(const QSizeF &delta, quint32 time, KWin::LibInput::Device *device = nullptr); + void processSwipeGestureUpdate(const QSizeF &delta, quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processSwipeGestureEnd(quint32 time, KWin::LibInput::Device *device = nullptr); + void processSwipeGestureEnd(quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processSwipeGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr); + void processSwipeGestureCancelled(quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processPinchGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device = nullptr); + void processPinchGestureBegin(int fingerCount, quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processPinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, KWin::LibInput::Device *device = nullptr); + void processPinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processPinchGestureEnd(quint32 time, KWin::LibInput::Device *device = nullptr); + void processPinchGestureEnd(quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processPinchGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr); + void processPinchGestureCancelled(quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processHoldGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device = nullptr); + void processHoldGestureBegin(int fingerCount, quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processHoldGestureEnd(quint32 time, KWin::LibInput::Device *device = nullptr); + void processHoldGestureEnd(quint32 time, KWin::InputDevice *device = nullptr); /** * @internal */ - void processHoldGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr); + void processHoldGestureCancelled(quint32 time, KWin::InputDevice *device = nullptr); private: - void processMotionInternal(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device); + void processMotionInternal(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, InputDevice *device); void cleanupInternalWindow(QWindow *old, QWindow *now) override; void cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now) override; @@ -164,7 +160,6 @@ private: void disconnectPointerConstraintsConnection(); void breakPointerConstraints(KWaylandServer::SurfaceInterface *surface); CursorImage *m_cursor; - bool m_supportsWarping; QPointF m_pos; QHash m_buttons; Qt::MouseButtons m_qtButtons; diff --git a/src/tablet_input.cpp b/src/tablet_input.cpp index 5f3d66e4f3..4c1c2835cc 100644 --- a/src/tablet_input.cpp +++ b/src/tablet_input.cpp @@ -11,7 +11,6 @@ #include "decorations/decoratedclient.h" #include "input_event.h" #include "input_event_spy.h" -#include "libinput/device.h" #include "pointer_input.h" #include "toplevel.h" #include "wayland_server.h" diff --git a/src/tabletmodemanager.cpp b/src/tabletmodemanager.cpp index 1c3d02d26b..56639d96c6 100644 --- a/src/tabletmodemanager.cpp +++ b/src/tabletmodemanager.cpp @@ -7,13 +7,10 @@ #include "tabletmodemanager.h" #include "input.h" +#include "inputdevice.h" #include "input_event.h" #include "input_event_spy.h" -#include "libinput/device.h" -#include "libinput/connection.h" - -#include #include namespace KWin @@ -60,31 +57,26 @@ public: : QObject(parent) , m_parent(parent) { - auto c = LibInput::Connection::self(); - if (!c) { - return; - } - connect(c, &LibInput::Connection::deviceAdded, this, &TabletModeTouchpadRemovedSpy::refresh); - connect(c, &LibInput::Connection::deviceRemoved, this, &TabletModeTouchpadRemovedSpy::refresh); + connect(input(), &InputRedirection::deviceAdded, this, &TabletModeTouchpadRemovedSpy::refresh); + connect(input(), &InputRedirection::deviceRemoved, this, &TabletModeTouchpadRemovedSpy::refresh); check(); } - void refresh(LibInput::Device* d) { - if (!d->isTouch() && !d->isPointer()) - return; - check(); + void refresh(InputDevice *inputDevice) + { + if (inputDevice->isTouch() || inputDevice->isPointer()) { + check(); + } } - void check() { - if (!LibInput::Connection::self()) { - return; - } - const auto devices = LibInput::Connection::self()->devices(); - const bool hasTouch = std::any_of(devices.constBegin(), devices.constEnd(), [](LibInput::Device* device){ return device->isTouch(); }); + void check() + { + const auto devices = input()->devices(); + const bool hasTouch = std::any_of(devices.constBegin(), devices.constEnd(), [](InputDevice *device) { return device->isTouch(); }); m_parent->setTabletModeAvailable(hasTouch); - const bool hasPointer = std::any_of(devices.constBegin(), devices.constEnd(), [](LibInput::Device* device){ return device->isPointer(); }); + const bool hasPointer = std::any_of(devices.constBegin(), devices.constEnd(), [](InputDevice *device) { return device->isPointer(); }); m_parent->setIsTablet(hasTouch && !hasPointer); } @@ -116,17 +108,12 @@ void KWin::TabletModeManager::hasTabletModeInputChanged(bool set) input()->installInputEventSpy(new TabletModeSwitchEventSpy(this)); setTabletModeAvailable(true); } else { - auto setupDetector = [this] { - auto spy = new TabletModeTouchpadRemovedSpy(this); - connect(input(), &InputRedirection::hasTabletModeSwitchChanged, spy, [spy](bool set){ - if (set) - spy->deleteLater(); - }); - }; - if (LibInput::Connection::self()) - setupDetector(); - else - QTimer::singleShot(2000, this, setupDetector); + auto spy = new TabletModeTouchpadRemovedSpy(this); + connect(input(), &InputRedirection::hasTabletModeSwitchChanged, spy, [spy](bool set) { + if (set) { + spy->deleteLater(); + } + }); } } diff --git a/src/touch_input.cpp b/src/touch_input.cpp index 36af3d57af..17c752c39e 100644 --- a/src/touch_input.cpp +++ b/src/touch_input.cpp @@ -38,6 +38,10 @@ TouchInputRedirection::~TouchInputRedirection() = default; void TouchInputRedirection::init() { Q_ASSERT(!inited()); + waylandServer()->seat()->setHasTouch(input()->hasTouch()); + connect(input(), &InputRedirection::hasTouchChanged, + waylandServer()->seat(), &KWaylandServer::SeatInterface::setHasTouch); + setInited(true); InputDeviceHandler::init(); @@ -135,7 +139,7 @@ void TouchInputRedirection::cleanupDecoration(Decoration::DecoratedClientImpl *o // nothing to do } -void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device) +void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, quint32 time, InputDevice *device) { Q_UNUSED(device) if (!inited()) { @@ -153,7 +157,7 @@ void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, quint32 t m_windowUpdatedInCycle = false; } -void TouchInputRedirection::processUp(qint32 id, quint32 time, LibInput::Device *device) +void TouchInputRedirection::processUp(qint32 id, quint32 time, InputDevice *device) { Q_UNUSED(device) if (!inited()) { @@ -172,7 +176,7 @@ void TouchInputRedirection::processUp(qint32 id, quint32 time, LibInput::Device } } -void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device) +void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, quint32 time, InputDevice *device) { Q_UNUSED(device) if (!inited()) { diff --git a/src/touch_input.h b/src/touch_input.h index b2f3801616..e49737e990 100644 --- a/src/touch_input.h +++ b/src/touch_input.h @@ -19,6 +19,7 @@ namespace KWin { +class InputDevice; class InputRedirection; class Toplevel; @@ -27,11 +28,6 @@ namespace Decoration class DecoratedClientImpl; } -namespace LibInput -{ -class Device; -} - class TouchInputRedirection : public InputDeviceHandler { Q_OBJECT @@ -43,9 +39,9 @@ public: bool focusUpdatesBlocked() override; void init() override; - void processDown(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device = nullptr); - void processUp(qint32 id, quint32 time, LibInput::Device *device = nullptr); - void processMotion(qint32 id, const QPointF &pos, quint32 time, LibInput::Device *device = nullptr); + void processDown(qint32 id, const QPointF &pos, quint32 time, InputDevice *device = nullptr); + void processUp(qint32 id, quint32 time, InputDevice *device = nullptr); + void processMotion(qint32 id, const QPointF &pos, quint32 time, InputDevice *device = nullptr); void cancel(); void frame(); diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp index 37d7bfa9b8..d20bf88165 100644 --- a/src/wayland_server.cpp +++ b/src/wayland_server.cpp @@ -13,6 +13,7 @@ #include "composite.h" #include "idle_inhibition.h" #include "inputpanelv1integration.h" +#include "keyboard_input.h" #include "screens.h" #include "layershellv1integration.h" #include "main.h" @@ -538,6 +539,10 @@ void WaylandServer::shellClientShown(Toplevel *toplevel) void WaylandServer::initWorkspace() { + // TODO: Moe the keyboard leds somewhere else. + updateKeyState(input()->keyboard()->xkb()->leds()); + connect(input()->keyboard(), &KeyboardInputRedirection::ledsChanged, this, &WaylandServer::updateKeyState); + VirtualDesktopManager::self()->setVirtualDesktopManagement(m_virtualDesktopManagement); if (m_windowManagement) {