ButtonRebindsFilter: Set cursor position when rebinding tablet events
Since the tablet cursor and the mouse cursor is tracked separately, rebinding a tablet button to a mouse click is sort of wonky. For example, if you assign it to Right Click and attempt to open a context menu it will appear to open in the wrong place. So before we send the mouse button event, set the mouse position to the tablet cursor position. A test is added to ensure this functionality works as intended and doesn't regress.
This commit is contained in:
parent
fd670453e5
commit
59699402ad
3 changed files with 64 additions and 0 deletions
|
@ -9,6 +9,7 @@
|
|||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "pointer_input.h"
|
||||
#include "tablet_input.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
|
||||
|
@ -42,6 +43,8 @@ private Q_SLOTS:
|
|||
void testBindingTabletPad();
|
||||
void testBindingTabletTool();
|
||||
|
||||
void testMouseTabletCursorSync();
|
||||
|
||||
private:
|
||||
quint32 timestamp = 1;
|
||||
};
|
||||
|
@ -238,5 +241,44 @@ void TestButtonRebind::testBindingTabletTool()
|
|||
Test::tabletToolButtonReleased(BTN_STYLUS, timestamp++);
|
||||
}
|
||||
|
||||
void TestButtonRebind::testMouseTabletCursorSync()
|
||||
{
|
||||
KConfigGroup buttonGroup = KSharedConfig::openConfig(QStringLiteral("kcminputrc"))->group(QStringLiteral("ButtonRebinds")).group(QStringLiteral("TabletTool")).group(QStringLiteral("Virtual Tablet Tool 1"));
|
||||
buttonGroup.writeEntry(QString::number(BTN_STYLUS), QStringList{"MouseButton", QString::number(BTN_LEFT)}, KConfig::Notify);
|
||||
buttonGroup.sync();
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
std::unique_ptr<KWayland::Client::Pointer> pointer(Test::waylandSeat()->createPointer());
|
||||
QSignalSpy enteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
|
||||
QSignalSpy buttonChangedSpy(pointer.get(), &KWayland::Client::Pointer::buttonStateChanged);
|
||||
|
||||
const QRectF startGeometry = window->frameGeometry();
|
||||
|
||||
// Move the mouse cursor to (25, 25)
|
||||
input()->pointer()->warp(startGeometry.topLeft() + QPointF{25.f, 25.5f});
|
||||
QVERIFY(enteredSpy.wait());
|
||||
|
||||
// Move the tablet cursor to (10,10)
|
||||
Test::tabletToolEvent(InputRedirection::Proximity, startGeometry.topLeft() + QPointF{10.f, 10.f}, 1.0, 0, 0, 0, false, false, timestamp++);
|
||||
|
||||
// Verify they are not starting in the same place
|
||||
QVERIFY(input()->pointer()->pos() != input()->tablet()->position());
|
||||
|
||||
// Send the tablet button event so it can be processed by the filter
|
||||
Test::tabletToolButtonPressed(BTN_STYLUS, timestamp++);
|
||||
|
||||
QVERIFY(buttonChangedSpy.wait());
|
||||
QCOMPARE(buttonChangedSpy.count(), 1);
|
||||
QCOMPARE(buttonChangedSpy.at(0).at(2).value<qint32>(), BTN_LEFT);
|
||||
|
||||
Test::tabletToolButtonReleased(BTN_STYLUS, timestamp++);
|
||||
|
||||
// Verify that by using the mouse button binding, the mouse cursor was moved to the tablet cursor position
|
||||
QVERIFY(input()->pointer()->pos() == input()->tablet()->position());
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(TestButtonRebind)
|
||||
#include "buttonrebind_test.moc"
|
||||
|
|
|
@ -205,6 +205,15 @@ bool ButtonRebindsFilter::pointerEvent(KWin::MouseEvent *event, quint32 nativeBu
|
|||
return send(Pointer, {{}, event->button()}, event->type() == QEvent::MouseButtonPress, event->timestamp());
|
||||
}
|
||||
|
||||
bool ButtonRebindsFilter::tabletToolEvent(KWin::TabletEvent *event)
|
||||
{
|
||||
if (RebindScope::isRebinding()) {
|
||||
return false;
|
||||
}
|
||||
m_tabletCursorPos = event->position();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ButtonRebindsFilter::tabletPadButtonEvent(uint button, bool pressed, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time)
|
||||
{
|
||||
if (RebindScope::isRebinding()) {
|
||||
|
@ -282,6 +291,9 @@ bool ButtonRebindsFilter::send(TriggerType type, const Trigger &trigger, bool pr
|
|||
return sendKeySequence(*seq, pressed, timestamp);
|
||||
}
|
||||
if (const auto mb = std::get_if<MouseButton>(&action)) {
|
||||
if (pressed && type != Pointer) {
|
||||
sendMousePosition(m_tabletCursorPos, timestamp);
|
||||
}
|
||||
return sendMouseButton(mb->button, pressed, timestamp);
|
||||
}
|
||||
if (const auto tb = std::get_if<TabletToolButton>(&action)) {
|
||||
|
@ -379,6 +391,13 @@ bool ButtonRebindsFilter::sendMouseButton(quint32 button, bool pressed, std::chr
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ButtonRebindsFilter::sendMousePosition(QPointF position, std::chrono::microseconds time)
|
||||
{
|
||||
RebindScope scope;
|
||||
Q_EMIT m_inputDevice.pointerMotionAbsolute(position, time, &m_inputDevice);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ButtonRebindsFilter::sendTabletToolButton(quint32 button, bool pressed, std::chrono::microseconds time)
|
||||
{
|
||||
if (!m_tabletTool) {
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
|
||||
explicit ButtonRebindsFilter();
|
||||
bool pointerEvent(KWin::MouseEvent *event, quint32 nativeButton) override;
|
||||
bool tabletToolEvent(KWin::TabletEvent *event) override;
|
||||
bool tabletPadButtonEvent(uint button, bool pressed, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time) override;
|
||||
bool tabletToolButtonEvent(uint button, bool pressed, const KWin::TabletToolId &tabletToolId, std::chrono::microseconds time) override;
|
||||
|
||||
|
@ -83,10 +84,12 @@ private:
|
|||
bool send(TriggerType type, const Trigger &trigger, bool pressed, std::chrono::microseconds timestamp);
|
||||
bool sendKeySequence(const QKeySequence &sequence, bool pressed, std::chrono::microseconds time);
|
||||
bool sendMouseButton(quint32 button, bool pressed, std::chrono::microseconds time);
|
||||
bool sendMousePosition(QPointF position, std::chrono::microseconds time);
|
||||
bool sendTabletToolButton(quint32 button, bool pressed, std::chrono::microseconds time);
|
||||
|
||||
InputDevice m_inputDevice;
|
||||
std::array<QHash<Trigger, std::variant<QKeySequence, MouseButton, TabletToolButton, DisabledButton>>, LastType> m_actions;
|
||||
KConfigWatcher::Ptr m_configWatcher;
|
||||
std::optional<KWin::TabletToolId> m_tabletTool;
|
||||
QPointF m_cursorPos, m_tabletCursorPos;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue