Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
6.5, 6.7
-
None
Description
Using Wintab (using the private headers or command line argument) leads to two
MouseButtonPress events being synthesized.
This messes up basically anything which toggles a state on press, like Menus for example.
So far only tested and confirmed with
XP-Pen devices (Artist Pro 16 and Artist 24 Pro)
Huion device (HS610)
Example demonstrating the issue with a Button with a menu and a simple button flipping a state on click.
I also included an ugly workaround with event filters (just accepting the Tablet event was not enough in my tests)
#include <QtGui/private/qguiapplication_p.h> #include <QtGui/qpa/qplatformintegration.h> #include <QDebug> #include <QApplication> #include <QPushButton> #include <QPainter> #include <QTabletEvent> #include <QMainWindow> #include <QMenu> using QWindowsApplication = QNativeInterface::Private::QWindowsApplication; bool is_wintab_enabled(){ auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration()); return nativeWindowsApp && nativeWindowsApp->isWinTabEnabled(); } void enable_wintab(bool state){ qDebug() << "Set wintab status to:" << state << "Current: " << is_wintab_enabled(); if (auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration())) nativeWindowsApp->setWinTabEnabled(state); qDebug() << "Post set wintab status to:" << state << "Current: " << is_wintab_enabled(); } class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent=nullptr) : QMainWindow(parent) { setMinimumSize(500, 500); // Simple state issue demonstration. // Ti all boils down to this issue QPushButton *btn = new QPushButton("Click me", this); connect(btn, &QPushButton::pressed, this, [this](){ state = !state; qDebug() << "Button pressed"; update(); }); // Demonstrating the issue with a simple menu QPushButton *menuButton = new QPushButton("Show menu", this); QMenu *menu = new QMenu(menuButton); menu->addMenu("TEst 1"); menu->addMenu("TEst 2"); menu->addMenu("TEst 3"); menuButton->setMenu(menu); menuButton->move(0, 30); } protected: bool state = false; void mousePressEvent(QMouseEvent *event) override { // Just to demonstrate the two press events we receive QMainWindow::mousePressEvent(event); qDebug() << "Mouse pressed" << event->pointingDevice()->pointerType(); } void mouseReleaseEvent(QMouseEvent *event) override { // We do NOT get two Release events QMainWindow::mouseReleaseEvent(event); qDebug() << "Mouse released"; } void paintEvent(QPaintEvent *event) override { // Just draw a different background based on state QPainter p(this); p.fillRect(rect(), state ? Qt::red : Qt::black); } }; class WinTabClickWorkaround : public QObject{ Q_OBJECT public: bool eventFilter(QObject *watched, QEvent *event) override{ if(event->type() == QEvent::MouseButtonPress){ QMouseEvent *evt = static_cast<QMouseEvent*>(event); if(evt->pointingDevice()->pointerType() == QPointingDevice::PointerType::Pen || evt->pointingDevice()->pointerType() == QPointingDevice::PointerType::Eraser){ assert(is_wintab_enabled()); // in my experience Windows Ink synthetised mouse events are never this type qDebug() << "Supress mouse"; return true; } } return QObject::eventFilter(watched, event); } }; #include "main.moc" int main(int argc, char *argv[]) { bool USE_WINTAB = true; bool USE_WORKAROUND = false; QApplication a(argc, argv); if(USE_WORKAROUND){ a.installEventFilter(new WinTabClickWorkaround()); } MainWindow w; if(USE_WINTAB){ enable_wintab(true); } w.show(); return a.exec(); }