Support for relative pointer motion events
Summary: If KWin interacts with Libinput the RelativePointerManager interface gets created on the Wayland server. The ForwardInputEventFilter does forward the relative motion events in addition to the normal motion events. In order to properly support the relative motion events as they are expected by the Wayland protocol the handling of pointer motion events got slightly adjusted: * Libinput Pointer event extended by the additional data points * Libinput Pointer event carries the delta as a QSizeF instead of QPointF * PointerInputRedirection adjusted to take a pointer motion event with more arguments * Custom QMouseEvent subclass adjusted to carry the additional members The DebugConsole is adjusted to show the relative motion events in addition to the global position. Test Plan: Verified the manager object is created and verified the events in DebugConsole. Unfortunately not aware of any test application. Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D2979
This commit is contained in:
parent
7843974a8a
commit
cc2f4e3240
14 changed files with 117 additions and 19 deletions
|
@ -58,7 +58,7 @@ void InputEventsTest::testInitMouseEvent()
|
|||
QFETCH(QEvent::Type, type);
|
||||
// now create our own event
|
||||
MouseEvent event(type, QPointF(100, 200), Qt::LeftButton, Qt::LeftButton | Qt::RightButton,
|
||||
Qt::ShiftModifier | Qt::ControlModifier, 300, &d);
|
||||
Qt::ShiftModifier | Qt::ControlModifier, 300, QSizeF(1, 2), QSizeF(3, 4), quint64(-1), &d);
|
||||
// and verify the contract of QMouseEvent
|
||||
QCOMPARE(event.type(), type);
|
||||
QCOMPARE(event.globalPos(), QPoint(100, 200));
|
||||
|
@ -70,6 +70,9 @@ void InputEventsTest::testInitMouseEvent()
|
|||
QCOMPARE(event.timestamp(), 300ul);
|
||||
// and our custom argument
|
||||
QCOMPARE(event.device(), &d);
|
||||
QCOMPARE(event.delta(), QSizeF(1, 2));
|
||||
QCOMPARE(event.deltaUnaccelerated(), QSizeF(3, 4));
|
||||
QCOMPARE(event.timestampMicroseconds(), quint64(-1));
|
||||
}
|
||||
|
||||
void InputEventsTest::testInitKeyEvent_data()
|
||||
|
|
|
@ -450,11 +450,26 @@ double libinput_event_pointer_get_dy(struct libinput_event_pointer *event)
|
|||
return event->delta.height();
|
||||
}
|
||||
|
||||
double libinput_event_pointer_get_dx_unaccelerated(struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->delta.width();
|
||||
}
|
||||
|
||||
double libinput_event_pointer_get_dy_unaccelerated(struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->delta.height();
|
||||
}
|
||||
|
||||
uint32_t libinput_event_pointer_get_time(struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->time;
|
||||
}
|
||||
|
||||
uint64_t libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event)
|
||||
{
|
||||
return quint64(event->time * 1000);
|
||||
}
|
||||
|
||||
uint32_t libinput_event_pointer_get_button(struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->button;
|
||||
|
|
|
@ -128,6 +128,7 @@ void TestLibinputPointerEvent::testButton()
|
|||
QTEST(pe->buttonState(), "expectedButtonState");
|
||||
QCOMPARE(pe->button(), button);
|
||||
QCOMPARE(pe->time(), time);
|
||||
QCOMPARE(pe->timeMicroseconds(), quint64(time * 1000));
|
||||
}
|
||||
|
||||
void TestLibinputPointerEvent::testAxis_data()
|
||||
|
@ -183,7 +184,7 @@ void TestLibinputPointerEvent::testMotion()
|
|||
QVERIFY(pe);
|
||||
QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_MOTION);
|
||||
QCOMPARE(pe->time(), 500u);
|
||||
QCOMPARE(pe->delta(), QPointF(2.1, 4.5));
|
||||
QCOMPARE(pe->delta(), QSizeF(2.1, 4.5));
|
||||
}
|
||||
|
||||
void TestLibinputPointerEvent::testAbsoluteMotion()
|
||||
|
|
|
@ -68,6 +68,11 @@ static QString timestampRow(quint32 timestamp)
|
|||
return tableRow(i18n("Timestamp"), timestamp);
|
||||
}
|
||||
|
||||
static QString timestampRowUsec(quint64 timestamp)
|
||||
{
|
||||
return tableRow(i18n("Timestamp (µsec)"), timestamp);
|
||||
}
|
||||
|
||||
static QString buttonToString(Qt::MouseButton button)
|
||||
{
|
||||
switch (button) {
|
||||
|
@ -171,14 +176,27 @@ bool DebugConsoleFilter::pointerEvent(QMouseEvent *event, quint32 nativeButton)
|
|||
|
||||
text.append(s_tableStart);
|
||||
switch (event->type()) {
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::MouseMove: {
|
||||
text.append(tableHeaderRow(i18nc("A mouse pointer motion event", "Pointer Motion")));
|
||||
auto e = static_cast<MouseEvent*>(event);
|
||||
#if HAVE_INPUT
|
||||
text.append(deviceRow(static_cast<MouseEvent*>(event)->device()));
|
||||
text.append(deviceRow(e->device()));
|
||||
#endif
|
||||
text.append(timestamp);
|
||||
if (e->timestampMicroseconds() != 0) {
|
||||
text.append(timestampRowUsec(e->timestampMicroseconds()));
|
||||
}
|
||||
if (e->delta() != QSizeF()) {
|
||||
text.append(tableRow(i18nc("The relative mouse movement", "Delta"),
|
||||
QStringLiteral("%1/%2").arg(e->delta().width()).arg(e->delta().height())));
|
||||
}
|
||||
if (e->deltaUnaccelerated() != QSizeF()) {
|
||||
text.append(tableRow(i18nc("The relative mouse movement", "Delta (not accelerated)"),
|
||||
QStringLiteral("%1/%2").arg(e->deltaUnaccelerated().width()).arg(e->deltaUnaccelerated().height())));
|
||||
}
|
||||
text.append(tableRow(i18nc("The global mouse pointer position", "Global Position"), QStringLiteral("%1/%2").arg(event->pos().x()).arg(event->pos().y())));
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonPress:
|
||||
text.append(tableHeaderRow(i18nc("A mouse pointer button press event", "Pointer Button Press")));
|
||||
#if HAVE_INPUT
|
||||
|
|
19
input.cpp
19
input.cpp
|
@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#include "input.h"
|
||||
#include "input_event.h"
|
||||
#include "keyboard_input.h"
|
||||
#include "pointer_input.h"
|
||||
#include "touch_input.h"
|
||||
|
@ -43,6 +44,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KWayland/Server/display.h>
|
||||
#include <KWayland/Server/fakeinput_interface.h>
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
#include <KWayland/Server/relativepointer_interface.h>
|
||||
#include <decorations/decoratedclient.h>
|
||||
#include <KDecoration2/Decoration>
|
||||
//screenlocker
|
||||
|
@ -892,13 +894,18 @@ public:
|
|||
auto seat = waylandServer()->seat();
|
||||
seat->setTimestamp(event->timestamp());
|
||||
switch (event->type()) {
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::MouseMove: {
|
||||
if (event->buttons() == Qt::NoButton) {
|
||||
// update pointer window only if no button is pressed
|
||||
input()->pointer()->update();
|
||||
}
|
||||
seat->setPointerPos(event->globalPos());
|
||||
MouseEvent *e = static_cast<MouseEvent*>(event);
|
||||
if (e->delta() != QSizeF()) {
|
||||
seat->relativePointerMotion(e->delta(), e->deltaUnaccelerated(), e->timestampMicroseconds());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonPress:
|
||||
seat->pointerButtonPressed(nativeButton);
|
||||
break;
|
||||
|
@ -1232,6 +1239,12 @@ void InputRedirection::setupLibInput()
|
|||
LibInput::Connection *conn = LibInput::Connection::create(this);
|
||||
m_libInput = conn;
|
||||
if (conn) {
|
||||
|
||||
if (waylandServer()) {
|
||||
// create relative pointer manager
|
||||
waylandServer()->display()->createRelativePointerManager(KWayland::Server::RelativePointerInterfaceVersion::UnstableV1, waylandServer()->display())->create();
|
||||
}
|
||||
|
||||
conn->setInputConfig(m_inputConfig);
|
||||
conn->setup();
|
||||
connect(conn, &LibInput::Connection::eventsRead, this,
|
||||
|
@ -1251,8 +1264,8 @@ void InputRedirection::setupLibInput()
|
|||
connect(conn, &LibInput::Connection::swipeGestureCancelled, m_pointer, &PointerInputRedirection::processSwipeGestureCancelled);
|
||||
connect(conn, &LibInput::Connection::keyChanged, m_keyboard, &KeyboardInputRedirection::processKey);
|
||||
connect(conn, &LibInput::Connection::pointerMotion, this,
|
||||
[this] (QPointF delta, uint32_t time, LibInput::Device *device) {
|
||||
m_pointer->processMotion(m_pointer->pos() + delta, time, device);
|
||||
[this] (const QSizeF &delta, const QSizeF &deltaNonAccel, uint32_t time, quint64 timeMicroseconds, LibInput::Device *device) {
|
||||
m_pointer->processMotion(m_pointer->pos() + QPointF(delta.width(), delta.height()), delta, deltaNonAccel, time, timeMicroseconds, device);
|
||||
}
|
||||
);
|
||||
connect(conn, &LibInput::Connection::pointerMotionAbsolute, this,
|
||||
|
|
|
@ -24,8 +24,12 @@ namespace KWin
|
|||
|
||||
MouseEvent::MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton button,
|
||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
|
||||
quint32 timestamp, LibInput::Device *device)
|
||||
quint32 timestamp, const QSizeF &delta, const QSizeF &deltaNonAccelerated,
|
||||
quint64 timestampMicroseconds, LibInput::Device *device)
|
||||
: QMouseEvent(type, pos, pos, button, buttons, modifiers)
|
||||
, m_delta(delta)
|
||||
, m_deltaUnccelerated(deltaNonAccelerated)
|
||||
, m_timestampMicroseconds(timestampMicroseconds)
|
||||
, m_device(device)
|
||||
{
|
||||
setTimestamp(timestamp);
|
||||
|
|
|
@ -33,13 +33,30 @@ class MouseEvent : public QMouseEvent
|
|||
{
|
||||
public:
|
||||
explicit MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton button, Qt::MouseButtons buttons,
|
||||
Qt::KeyboardModifiers modifiers, quint32 timestamp, LibInput::Device *device);
|
||||
Qt::KeyboardModifiers modifiers, quint32 timestamp,
|
||||
const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 timestampMicroseconds,
|
||||
LibInput::Device *device);
|
||||
|
||||
QSizeF delta() const {
|
||||
return m_delta;
|
||||
}
|
||||
|
||||
QSizeF deltaUnaccelerated() const {
|
||||
return m_deltaUnccelerated;
|
||||
}
|
||||
|
||||
quint64 timestampMicroseconds() const {
|
||||
return m_timestampMicroseconds;
|
||||
}
|
||||
|
||||
LibInput::Device *device() const {
|
||||
return m_device;
|
||||
}
|
||||
|
||||
private:
|
||||
QSizeF m_delta;
|
||||
QSizeF m_deltaUnccelerated;
|
||||
quint64 m_timestampMicroseconds;
|
||||
LibInput::Device *m_device;
|
||||
};
|
||||
|
||||
|
|
|
@ -328,20 +328,24 @@ void Connection::processEvents()
|
|||
}
|
||||
case LIBINPUT_EVENT_POINTER_MOTION: {
|
||||
PointerEvent *pe = static_cast<PointerEvent*>(event.data());
|
||||
QPointF delta = pe->delta();
|
||||
auto delta = pe->delta();
|
||||
auto deltaNonAccel = pe->deltaUnaccelerated();
|
||||
quint32 latestTime = pe->time();
|
||||
quint64 latestTimeUsec = pe->timeMicroseconds();
|
||||
auto it = m_eventQueue.begin();
|
||||
while (it != m_eventQueue.end()) {
|
||||
if ((*it)->type() == LIBINPUT_EVENT_POINTER_MOTION) {
|
||||
QScopedPointer<PointerEvent> p(static_cast<PointerEvent*>(*it));
|
||||
delta += p->delta();
|
||||
deltaNonAccel += p->deltaUnaccelerated();
|
||||
latestTime = p->time();
|
||||
latestTimeUsec = p->timeMicroseconds();
|
||||
it = m_eventQueue.erase(it);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit pointerMotion(delta, latestTime, pe->device());
|
||||
emit pointerMotion(delta, deltaNonAccel, latestTime, latestTimeUsec, pe->device());
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: {
|
||||
|
|
|
@ -86,7 +86,7 @@ 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(QPointF orig, QPointF screen, quint32 time, KWin::LibInput::Device *device);
|
||||
void pointerMotion(QPointF delta, 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, quint32 time, KWin::LibInput::Device *device);
|
||||
void touchFrame(KWin::LibInput::Device *device);
|
||||
void touchCanceled(KWin::LibInput::Device *device);
|
||||
|
|
|
@ -133,10 +133,16 @@ QPointF PointerEvent::absolutePos(const QSize &size) const
|
|||
libinput_event_pointer_get_absolute_y_transformed(m_pointerEvent, size.height()));
|
||||
}
|
||||
|
||||
QPointF PointerEvent::delta() const
|
||||
QSizeF PointerEvent::delta() const
|
||||
{
|
||||
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION);
|
||||
return QPointF(libinput_event_pointer_get_dx(m_pointerEvent), libinput_event_pointer_get_dy(m_pointerEvent));
|
||||
return QSizeF(libinput_event_pointer_get_dx(m_pointerEvent), libinput_event_pointer_get_dy(m_pointerEvent));
|
||||
}
|
||||
|
||||
QSizeF PointerEvent::deltaUnaccelerated() const
|
||||
{
|
||||
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION);
|
||||
return QSizeF(libinput_event_pointer_get_dx_unaccelerated(m_pointerEvent), libinput_event_pointer_get_dy_unaccelerated(m_pointerEvent));
|
||||
}
|
||||
|
||||
uint32_t PointerEvent::time() const
|
||||
|
@ -144,6 +150,11 @@ uint32_t PointerEvent::time() const
|
|||
return libinput_event_pointer_get_time(m_pointerEvent);
|
||||
}
|
||||
|
||||
quint64 PointerEvent::timeMicroseconds() const
|
||||
{
|
||||
return libinput_event_pointer_get_time_usec(m_pointerEvent);
|
||||
}
|
||||
|
||||
uint32_t PointerEvent::button() const
|
||||
{
|
||||
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
|
|
@ -89,10 +89,12 @@ public:
|
|||
|
||||
QPointF absolutePos() const;
|
||||
QPointF absolutePos(const QSize &size) const;
|
||||
QPointF delta() const;
|
||||
QSizeF delta() const;
|
||||
QSizeF deltaUnaccelerated() const;
|
||||
uint32_t button() const;
|
||||
InputRedirection::PointerButtonState buttonState() const;
|
||||
uint32_t time() const;
|
||||
quint64 timeMicroseconds() const;
|
||||
QVector<InputRedirection::PointerAxis> axis() const;
|
||||
qreal axisValue(InputRedirection::PointerAxis a) const;
|
||||
|
||||
|
|
|
@ -161,13 +161,19 @@ void PointerInputRedirection::init()
|
|||
}
|
||||
|
||||
void PointerInputRedirection::processMotion(const QPointF &pos, uint32_t time, LibInput::Device *device)
|
||||
{
|
||||
processMotion(pos, QSizeF(), QSizeF(), time, 0, device);
|
||||
}
|
||||
|
||||
void PointerInputRedirection::processMotion(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device)
|
||||
{
|
||||
if (!m_inited) {
|
||||
return;
|
||||
}
|
||||
updatePosition(pos);
|
||||
MouseEvent event(QEvent::MouseMove, m_pos, Qt::NoButton, m_qtButtons,
|
||||
m_input->keyboardModifiers(), time, device);
|
||||
m_input->keyboardModifiers(), time,
|
||||
delta, deltaNonAccelerated, timeUsec, device);
|
||||
|
||||
const auto &filters = m_input->filters();
|
||||
for (auto it = filters.begin(), end = filters.end(); it != end; it++) {
|
||||
|
@ -199,7 +205,7 @@ void PointerInputRedirection::processButton(uint32_t button, InputRedirection::P
|
|||
}
|
||||
|
||||
MouseEvent event(type, m_pos, buttonToQtMouseButton(button), m_qtButtons,
|
||||
m_input->keyboardModifiers(), time, device);
|
||||
m_input->keyboardModifiers(), time, QSizeF(), QSizeF(), 0, device);
|
||||
|
||||
const auto &filters = m_input->filters();
|
||||
for (auto it = filters.begin(), end = filters.end(); it != end; it++) {
|
||||
|
|
|
@ -86,6 +86,10 @@ public:
|
|||
* @internal
|
||||
*/
|
||||
void processMotion(const QPointF &pos, uint32_t time, LibInput::Device *device = nullptr);
|
||||
/**
|
||||
* @internal
|
||||
**/
|
||||
void processMotion(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device);
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
|
|
@ -75,8 +75,8 @@ int main(int argc, char **argv)
|
|||
}
|
||||
);
|
||||
QObject::connect(conn, &Connection::pointerMotion,
|
||||
[](QPointF delta) {
|
||||
std::cout << "Got pointer motion: " << delta.x() << "/" << delta.y() << std::endl;
|
||||
[](const QSizeF &delta) {
|
||||
std::cout << "Got pointer motion: " << delta.width() << "/" << delta.height() << std::endl;
|
||||
}
|
||||
);
|
||||
QObject::connect(conn, &Connection::pointerAxisChanged,
|
||||
|
|
Loading…
Reference in a new issue