Skip to content

Commit

Permalink
Ignore spontaneous tablet events in canvas instead
Browse files Browse the repository at this point in the history
Rather than doing it with an event filter, because that apparently
doesn't work properly and still lets spontaneous events through. They're
now ignored in the canvas controller/canvas view instead.
  • Loading branch information
askmeaboutlo0m committed Nov 24, 2024
1 parent 6e84573 commit eb17fca
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 70 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Unreleased Version 2.2.2-pre
* Fix: Don't carry over HUD button presses to dock UI in small screen mode. Thanks Meru for reporting.
* Feature: Make list action buttons in settings dialog clearer, adding an edit button for canvas shortcuts. Thanks Maffi for suggesting.
* Fix: Work around broken transparency when copying images between canvases on Wayland. Thanks Absolute Goober for reporting.
* Fix: Properly ignore system tablet events when using KisTablet drivers on Windows. Thanks Doc for reporting.

2024-11-06 Version 2.2.2-beta.4
* Fix: Solve rendering glitches with selection outlines that happen on some systems. Thanks xxxx for reporting.
Expand Down
34 changes: 25 additions & 9 deletions src/desktop/scene/canvasview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2006,16 +2006,21 @@ bool CanvasView::viewportEvent(QEvent *event)
QTabletEvent *tabev = static_cast<QTabletEvent *>(event);
const auto tabPos = compat::tabPosF(*tabev);
Qt::KeyboardModifiers modifiers = getTabletModifiers(tabev);
bool spontaneous = tabev->spontaneous();
bool ignore = spontaneous && tabletinput::ignoreSpontaneous();
DP_EVENT_LOG(
"tablet_press spontaneous=%d x=%f y=%f pressure=%f xtilt=%d "
"ytilt=%d rotation=%f buttons=0x%x modifiers=0x%x pendown=%d "
"touching=%d effectivemodifiers=0x%u",
tabev->spontaneous(), tabPos.x(), tabPos.y(), tabev->pressure(),
"touching=%d effectivemodifiers=0x%u ignore=%d",
spontaneous, tabPos.x(), tabPos.y(), tabev->pressure(),
compat::cast_6<int>(tabev->xTilt()),
compat::cast_6<int>(tabev->yTilt()),
qDegreesToRadians(tabev->rotation()), unsigned(tabev->buttons()),
unsigned(tabev->modifiers()), m_pendown, m_touch->isTouching(),
unsigned(modifiers));
unsigned(modifiers), int(ignore));
if(ignore) {
return true;
}

Qt::MouseButton button;
bool eraserOverride;
Expand Down Expand Up @@ -2057,16 +2062,21 @@ bool CanvasView::viewportEvent(QEvent *event)
const auto tabPos = compat::tabPosF(*tabev);
Qt::KeyboardModifiers modifiers = getTabletModifiers(tabev);
Qt::MouseButtons buttons = tabev->buttons();
bool spontaneous = tabev->spontaneous();
bool ignore = spontaneous && tabletinput::ignoreSpontaneous();
DP_EVENT_LOG(
"tablet_move spontaneous=%d x=%f y=%f pressure=%f xtilt=%d "
"ytilt=%d rotation=%f buttons=0x%x modifiers=0x%x pendown=%d "
"touching=%d effectivemodifiers=0x%u",
tabev->spontaneous(), tabPos.x(), tabPos.y(), tabev->pressure(),
"touching=%d effectivemodifiers=0x%u ignore=%d",
int(spontaneous), tabPos.x(), tabPos.y(), tabev->pressure(),
compat::cast_6<int>(tabev->xTilt()),
compat::cast_6<int>(tabev->yTilt()),
qDegreesToRadians(tabev->rotation()), unsigned(buttons),
unsigned(tabev->modifiers()), m_pendown, m_touch->isTouching(),
unsigned(modifiers));
unsigned(modifiers), int(ignore));
if(ignore) {
return true;
}

if(!tabletinput::passPenEvents()) {
tabev->accept();
Expand All @@ -2091,12 +2101,18 @@ bool CanvasView::viewportEvent(QEvent *event)
QTabletEvent *tabev = static_cast<QTabletEvent *>(event);
const auto tabPos = compat::tabPosF(*tabev);
Qt::KeyboardModifiers modifiers = getTabletModifiers(tabev);
bool spontaneous = tabev->spontaneous();
bool ignore = spontaneous && tabletinput::ignoreSpontaneous();
DP_EVENT_LOG(
"tablet_release spontaneous=%d x=%f y=%f buttons=0x%x pendown=%d "
"touching=%d effectivemodifiers=0x%u",
tabev->spontaneous(), tabPos.x(), tabPos.y(),
"touching=%d effectivemodifiers=0x%u ignore=%d",
int(spontaneous), tabPos.x(), tabPos.y(),
unsigned(tabev->buttons()), m_pendown, m_touch->isTouching(),
unsigned(modifiers));
unsigned(modifiers), int(ignore));
if(ignore) {
return true;
}

updateCursorPos(tabPos.toPoint());
if(!tabletinput::passPenEvents()) {
tabev->accept();
Expand Down
57 changes: 8 additions & 49 deletions src/desktop/tabletinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,12 @@ static Mode currentMode = Mode::Uninitialized;

#ifdef Q_OS_WIN

class SpontaneousTabletEventFilter final : public QObject {
public:
explicit SpontaneousTabletEventFilter(QObject *parent)
: QObject{parent}
{
}

protected:
bool eventFilter(QObject *watched, QEvent *event) override final
{
switch(event->type()) {
case QEvent::TabletEnterProximity:
case QEvent::TabletLeaveProximity:
case QEvent::TabletMove:
case QEvent::TabletPress:
case QEvent::TabletRelease:
// KisTablet uses QApplication::sendEvent, which means its events
// are never set to be spontaneous. We use that to filter out Qt's
// own tablet events, which in turn are always spontaneous.
if(event->spontaneous()) {
return false;
}
[[fallthrough]];
default:
return QObject::eventFilter(watched, event);
}
}
};

static KisTabletSupportWin8 *kisTabletSupportWin8;
static SpontaneousTabletEventFilter *spontaneousTabletEventFilter;
static bool shouldPassPenEvents = true;

static void resetKisTablet(DrawpileApp &app)
{
if(spontaneousTabletEventFilter) {
app.removeEventFilter(spontaneousTabletEventFilter);
delete spontaneousTabletEventFilter;
spontaneousTabletEventFilter = nullptr;
}
shouldPassPenEvents = true;
if(kisTabletSupportWin8) {
app.removeNativeEventFilter(kisTabletSupportWin8);
delete kisTabletSupportWin8;
Expand All @@ -67,17 +34,11 @@ static void resetKisTablet(DrawpileApp &app)
KisTabletSupportWin::quit();
}

static void installSpontaneousTabletEventFilter(DrawpileApp &app)
{
spontaneousTabletEventFilter = new SpontaneousTabletEventFilter{&app};
app.installEventFilter(spontaneousTabletEventFilter);
}

static void enableKisTabletWinink(DrawpileApp &app)
{
kisTabletSupportWin8 = new KisTabletSupportWin8;
if(kisTabletSupportWin8->init()) {
installSpontaneousTabletEventFilter(app);
shouldPassPenEvents = false;
app.installNativeEventFilter(kisTabletSupportWin8);
currentMode = Mode::KisTabletWinink;
} else {
Expand All @@ -87,10 +48,10 @@ static void enableKisTabletWinink(DrawpileApp &app)
}
}

static void enableKisTabletWintab(DrawpileApp &app, bool relativePenModeHack)
static void enableKisTabletWintab(bool relativePenModeHack)
{
if(KisTabletSupportWin::init()) {
installSpontaneousTabletEventFilter(app);
shouldPassPenEvents = false;
KisTabletSupportWin::enableRelativePenModeHack(relativePenModeHack);
if(relativePenModeHack) {
currentMode = Mode::KisTabletWintabRelativePenHack;
Expand Down Expand Up @@ -148,10 +109,10 @@ void init(DrawpileApp &app)
enableKisTabletWinink(app);
break;
case Mode::KisTabletWintab:
enableKisTabletWintab(app, false);
enableKisTabletWintab(false);
break;
case Mode::KisTabletWintabRelativePenHack:
enableKisTabletWintab(app, true);
enableKisTabletWintab(true);
break;
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
case Mode::Qt5:
Expand Down Expand Up @@ -201,9 +162,7 @@ const char *current()
#ifdef Q_OS_WIN
bool passPenEvents()
{
// The spontaneous event filter is installed if and only if a KisTablet
// input mode is currently active.
return !spontaneousTabletEventFilter;
return shouldPassPenEvents;
}
#endif

Expand Down
10 changes: 10 additions & 0 deletions src/desktop/tabletinput.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,21 @@ const char *current();
// meaning we don't double up on them and the view acts properly.
#ifdef Q_OS_WIN
bool passPenEvents();

inline bool ignoreSpontaneous()
{
return !passPenEvents();
}
#else
constexpr bool passPenEvents()
{
return true;
}

constexpr bool ignoreSpontaneous()
{
return false;
}
#endif

}
Expand Down
42 changes: 30 additions & 12 deletions src/desktop/view/canvascontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ extern "C" {
}
#include "desktop/main.h"
#include "desktop/scene/toggleitem.h"
#include "desktop/tabletinput.h"
#include "desktop/utils/qtguicompat.h"
#include "desktop/utils/touchhandler.h"
#include "desktop/view/canvascontroller.h"
Expand Down Expand Up @@ -668,13 +669,19 @@ void CanvasController::handleTabletMove(QTabletEvent *event)
qreal yTilt = event->yTilt();
Qt::KeyboardModifiers modifiers = getTabletModifiers(event);
Qt::MouseButtons buttons = event->buttons();
bool spontaneous = event->spontaneous();
bool ignore = spontaneous && tabletinput::ignoreSpontaneous();
DP_EVENT_LOG(
"tablet_move spontaneous=%d x=%f y=%f pressure=%f xtilt=%f "
"ytilt=%f rotation=%f buttons=0x%x modifiers=0x%x penstate=%d "
"touching=%d effectivemodifiers=0x%u",
int(event->spontaneous()), posf.x(), posf.y(), pressure, xTilt,
yTilt, rotation, unsigned(buttons), unsigned(event->modifiers()),
int(m_penState), int(m_touch->isTouching()), unsigned(modifiers));
"touching=%d effectivemodifiers=0x%u ignore=%d",
int(spontaneous), posf.x(), posf.y(), pressure, xTilt, yTilt,
rotation, unsigned(buttons), unsigned(event->modifiers()),
int(m_penState), int(m_touch->isTouching()), unsigned(modifiers),
int(ignore));
if(ignore) {
return;
}

// Under Windows Ink, some tablets report bogus zero-pressure inputs.
// We accept them so that they don't result in synthesized mouse events,
Expand Down Expand Up @@ -704,13 +711,19 @@ void CanvasController::handleTabletPress(QTabletEvent *event)
qreal xTilt = event->xTilt();
qreal yTilt = event->yTilt();
Qt::KeyboardModifiers modifiers = getTabletModifiers(event);
bool spontaneous = event->spontaneous();
bool ignore = spontaneous && tabletinput::ignoreSpontaneous();
DP_EVENT_LOG(
"tablet_press spontaneous=%d x=%f y=%f pressure=%f xtilt=%f "
"ytilt=%f rotation=%f buttons=0x%x modifiers=0x%x penstate=%d "
"touching=%d effectivemodifiers=0x%u",
int(event->spontaneous()), posf.x(), posf.y(), pressure, xTilt,
yTilt, rotation, unsigned(buttons), unsigned(event->modifiers()),
int(m_penState), int(m_touch->isTouching()), unsigned(modifiers));
"touching=%d effectivemodifiers=0x%u ignore=%d",
int(spontaneous), posf.x(), posf.y(), pressure, xTilt, yTilt,
rotation, unsigned(buttons), unsigned(event->modifiers()),
int(m_penState), int(m_touch->isTouching()), unsigned(modifiers),
int(ignore));
if(ignore) {
return;
}

Qt::MouseButton button;
bool eraserOverride;
Expand Down Expand Up @@ -744,12 +757,17 @@ void CanvasController::handleTabletRelease(QTabletEvent *event)

QPointF posf = tabletPosF(event);
Qt::KeyboardModifiers modifiers = getTabletModifiers(event);
bool spontaneous = event->spontaneous();
bool ignore = spontaneous && tabletinput::ignoreSpontaneous();
DP_EVENT_LOG(
"tablet_release spontaneous=%d x=%f y=%f buttons=0x%x penstate=%d "
"touching=%d effectivemodifiers=0x%u",
int(event->spontaneous()), posf.x(), posf.y(),
unsigned(event->buttons()), int(m_penState),
int(m_touch->isTouching()), unsigned(modifiers));
"touching=%d effectivemodifiers=0x%u ignore=%d",
int(spontaneous), posf.x(), posf.y(), unsigned(event->buttons()),
int(m_penState), int(m_touch->isTouching()), unsigned(modifiers),
int(ignore));
if(ignore) {
return;
}

penReleaseEvent(
QDateTime::currentMSecsSinceEpoch(), posf, event->button(),
Expand Down

0 comments on commit eb17fca

Please sign in to comment.