Introduce base InputDevice class

The main motivation behind this change is to prepare input abstractions
for virtual input devices so the wl_seat can properly advertise caps or
the cursor getting properly mapped/unmapped when a fake pointer is
added/removed on a system without a hardware mouse connected.

With this, there are three abstractions - InputDevice, InputBackend, and
InputRedirection.

An InputDevice represents an input device such as a mouse, a keyboard, a
tablet, etc. The InputBackend class notifies the InputRedirection about
(dis-)connected devices. The InputRedirection manages the input devices.

Such design allows to unify the event flow for real and virtual input
devices.

There can be several input backends active. For example, the libinput
backend and an input backend that provides virtual input devices, e.g.
libeis or org_kde_kwin_fake_input.
This commit is contained in:
Vlad Zahorodnii 2021-10-02 11:26:51 +03:00
parent 4206046f12
commit ef72bae42f
44 changed files with 808 additions and 755 deletions

View file

@ -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)

View file

@ -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)
}

View file

@ -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

View file

@ -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<LibInput::Device *>(sender());
const auto device = static_cast<InputDevice *>(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) {

View file

@ -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<LibInput::Device*> m_devices;
void setupDeviceConnections(InputDevice *device);
QList<InputDevice *> m_devices;
};
class DataSourceModel : public QAbstractItemModel

View file

@ -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 <KWaylandServer/shmclientbuffer.h>
#include <KWaylandServer/surface_interface.h>
#include <KWaylandServer/tablet_v2_interface.h>
#include <KWaylandServer/keyboard_interface.h>
#include <decorations/decoratedclient.h>
//screenlocker
#include <KScreenLocker/KsldApp>
// Qt
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusPendingCall>
#include <QKeyEvent>
#include <QThread>
#include <qpa/qwindowsysteminterface.h>
@ -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<LibInput::Device *>(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<LibInput::Device *>(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<KWin::InputRedirection::KeyboardKeyState>();
qRegisterMetaType<KWin::InputRedirection::PointerButtonState>();
qRegisterMetaType<KWin::InputRedirection::PointerAxis>();
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<LibInput::Device *> 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

View file

@ -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<InputDevice *> devices() const;
bool hasAlphaNumericKeyboard();
bool hasPointer() const;
bool hasTouch() const;
bool hasTabletModeSwitch();
void startInteractiveWindowSelection(std::function<void(KWin::Toplevel*)> callback, const QByteArray &cursorName);
void startInteractivePositionSelection(std::function<void(const QPoint &)> 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<InputBackend *> m_inputBackends;
QList<InputDevice *> m_inputDevices;
WindowSelectorFilter *m_windowSelector = nullptr;
@ -298,6 +309,14 @@ private:
QVector<InputEventSpy*> 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<InputDevice *> InputRedirection::devices() const
{
return m_inputDevices;
}
template <typename T, typename Slot>
inline
void InputRedirection::registerShortcut(const QKeySequence &shortcut, QAction *action, T *receiver, Slot slot) {

View file

@ -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)

View file

@ -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

27
src/inputbackend.cpp Normal file
View file

@ -0,0 +1,27 @@
/*
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
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

40
src/inputbackend.h Normal file
View file

@ -0,0 +1,40 @@
/*
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "kwin_export.h"
#include <KSharedConfig>
#include <QObject>
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

17
src/inputdevice.cpp Normal file
View file

@ -0,0 +1,17 @@
/*
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "inputdevice.h"
namespace KWin
{
InputDevice::InputDevice(QObject *parent)
: QObject(parent)
{
}
} // namespace KWin

83
src/inputdevice.h Normal file
View file

@ -0,0 +1,83 @@
/*
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "kwin_export.h"
#include "input.h"
#include <QObject>
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

View file

@ -20,6 +20,7 @@
#include "workspace.h"
// KWayland
#include <KWaylandServer/datadevice_interface.h>
#include <KWaylandServer/keyboard_interface.h>
#include <KWaylandServer/seat_interface.h>
//screenlocker
#include <KScreenLocker/KsldApp>
@ -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;

View file

@ -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
*/

View file

@ -25,9 +25,7 @@
#include "udev.h"
#include "libinput_logging.h"
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDBusPendingCall>
#include <QMutexLocker>
#include <QSocketNotifier>
@ -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<libinput_led>(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<KeyEvent*>(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<PointerEvent*>(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<PointerEvent*>(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<PointerEvent*>(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<TouchEvent*>(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<PinchGestureEvent*>(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<PinchGestureEvent*>(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<PinchGestureEvent*>(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<SwipeGestureEvent*>(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<SwipeGestureEvent*>(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<SwipeGestureEvent*>(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<HoldGestureEvent*>(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<HoldGestureEvent*>(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<SwitchEvent*>(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<TabletToolButtonEvent *>(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<TabletPadButtonEvent *>(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<TabletPadRingEvent *>(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<TabletPadStripEvent *>(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<libinput_led>(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) {

View file

@ -11,7 +11,7 @@
#include <kwinglobals.h>
#include "input.h"
#include <KSharedConfig>
#include <QObject>
#include <QPointer>
@ -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<Device*> 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<Event*> m_eventQueue;
bool wasSuspended = false;
QVector<Device*> m_devices;
KSharedConfigPtr m_config;
bool m_touchpadsEnabled = true;
LEDs m_leds;
KWIN_SINGLETON(Connection)
};

View file

@ -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));
}
}
}
}

View file

@ -9,6 +9,8 @@
#ifndef KWIN_LIBINPUT_DEVICE_H
#define KWIN_LIBINPUT_DEVICE_H
#include "inputdevice.h"
#include <libinput.h>
#include <KConfigGroup>
@ -18,7 +20,6 @@
#include <QPointer>
#include <QSizeF>
#include <QVector>
#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<Device*> s_devices;
};

View file

@ -0,0 +1,51 @@
/*
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
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

View file

@ -0,0 +1,36 @@
/*
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "inputbackend.h"
#include <QThread>
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

View file

@ -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<Platform *>(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();

View file

@ -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();

View file

@ -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;

View file

@ -76,6 +76,11 @@ void Platform::doShowCursor()
{
}
InputBackend *Platform::createInputBackend()
{
return nullptr;
}
OpenGLBackend *Platform::createOpenGLBackend()
{
return nullptr;

View file

@ -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) {

View file

@ -86,6 +86,5 @@
"Name[x-test]": "xxdrmxx",
"Name[zh_CN]": "drm",
"Name[zh_TW]": "drm"
},
"input": false
}
}

View file

@ -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 <KWaylandServer/seat_interface.h>
// KF5
#include <KCoreAddons>
#include <KLocalizedString>
@ -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));

View file

@ -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;

View file

@ -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);

View file

@ -50,6 +50,7 @@ public:
explicit FramebufferBackend(QObject *parent = nullptr);
~FramebufferBackend() override;
InputBackend *createInputBackend() override;
QPainterBackend *createQPainterBackend() override;
QSize screenSize() const override;

View file

@ -86,6 +86,5 @@
"Name[x-test]": "xxframebufferxx",
"Name[zh_CN]": "framebuffer",
"Name[zh_TW]": "framebuffer"
},
"input": false
}
}

View file

@ -86,6 +86,5 @@
"Name[x-test]": "xxvirtualxx",
"Name[zh_CN]": "virtual",
"Name[zh_TW]": "虛擬"
},
"input": true
}
}

View file

@ -84,6 +84,5 @@
"Name[x-test]": "xxwaylandxx",
"Name[zh_CN]": "wayland",
"Name[zh_TW]": "wayland"
},
"input": true
}
}

View file

@ -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);
}
);

View file

@ -83,6 +83,5 @@
"Name[x-test]": "xxx11-standalonexx",
"Name[zh_CN]": "x11-standalone",
"Name[zh_TW]": "x11-standalone"
},
"input": true
}
}

View file

@ -84,6 +84,5 @@
"Name[x-test]": "xxx11xx",
"Name[zh_CN]": "x11",
"Name[zh_TW]": "x11"
},
"input": true
}
}

View file

@ -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::ScheduledPosition> 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()

View file

@ -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<uint32_t, InputRedirection::PointerButtonState> m_buttons;
Qt::MouseButtons m_qtButtons;

View file

@ -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"

View file

@ -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 <QTimer>
#include <QDBusConnection>
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();
}
});
}
}

View file

@ -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()) {

View file

@ -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();

View file

@ -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) {