diff --git a/libs/ui/input/wintab/drawpile_tablettester/README.md b/libs/ui/input/wintab/drawpile_tablettester/README.md
new file mode 100644
index 0000000000..40b9e97ee8
--- /dev/null
+++ b/libs/ui/input/wintab/drawpile_tablettester/README.md
@@ -0,0 +1,17 @@
+Notes on code originating from external source:
+
+Tablet Tester
+=============
+
+Files are taken and possibly modified from the git repo of [Drawpile] on
+commit bc06dceba83e8c758d25cfe81b986e18f38aae95.
+
+[Drawpile]: https://github.com/drawpile/Drawpile
+
+File | Original in repo of Drawpile
+-------------------- | ---
+tablettester.cpp | src/desktop/dialogs/tablettester.cpp
+tablettester.h | src/desktop/dialogs/tablettester.h
+tablettest.cpp | src/desktop/widgets/tablettest.cpp
+tablettest.h | src/desktop/widgets/tablettest.h
+tablettest.ui | src/desktop/ui/tablettest.ui
diff --git a/libs/ui/input/wintab/drawpile_tablettester/tablettest.cpp b/libs/ui/input/wintab/drawpile_tablettester/tablettest.cpp
new file mode 100644
index 0000000000..86a1193285
--- /dev/null
+++ b/libs/ui/input/wintab/drawpile_tablettester/tablettest.cpp
@@ -0,0 +1,139 @@
+/*
+ Drawpile - a collaborative drawing program.
+
+ Copyright (C) 2017 Calle Laakkonen
+
+ Drawpile is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Drawpile is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Drawpile. If not, see .
+*/
+
+#include "tablettest.h"
+
+#include
+#include
+
+#ifndef DESIGNER_PLUGIN
+namespace widgets {
+#endif
+
+TabletTester::TabletTester(QWidget *parent)
+ : QWidget(parent), m_mouseDown(false), m_tabletDown(false)
+{
+}
+
+void TabletTester::clear()
+{
+ m_mousePath.clear();
+ m_tabletPath.clear();
+ update();
+}
+
+void TabletTester::paintEvent(QPaintEvent *e)
+{
+ Q_UNUSED(e);
+ const int w = width();
+ const int h = height();
+ QPainter p(this);
+ p.fillRect(0, 0, w, h, QColor(200, 200, 200));
+ p.setPen(QColor(128, 128, 128));
+
+ // Draw grid
+ for(int i=w/8;ix()).arg(e->y()).arg(e->button()));
+ m_mouseDown = true;
+ m_mousePath.clear();
+ update();
+}
+
+void TabletTester::mouseMoveEvent(QMouseEvent *e)
+{
+ emit eventReport(QString("Mouse move X=%1 Y=%2 B=%3").arg(e->x()).arg(e->y()).arg(e->buttons()));
+ m_mousePath << e->pos();
+ update();
+}
+
+void TabletTester::mouseReleaseEvent(QMouseEvent *e)
+{
+ Q_UNUSED(e);
+ emit eventReport(QString("Mouse release"));
+ m_mouseDown = false;
+}
+
+void TabletTester::tabletEvent(QTabletEvent *e)
+{
+ e->accept();
+
+ QString msg;
+ switch(e->device()) {
+ case QTabletEvent::Stylus: msg = "Stylus"; break;
+ default: msg = QString("Device(%1)").arg(e->device()); break;
+ }
+
+ switch(e->type()) {
+ case QEvent::TabletMove:
+ msg += " move";
+ break;
+ case QEvent::TabletPress:
+ msg += " press";
+ m_tabletPath.clear();
+ m_tabletDown = true;
+ break;
+ case QEvent::TabletRelease:
+ msg += " release";
+ m_tabletDown = false;
+ break;
+ default:
+ msg += QString(" event-%1").arg(e->type());
+ break;
+ }
+
+ msg += QString(" X=%1 Y=%2 B=%3 P=%4%")
+ .arg(e->posF().x(), 0, 'f', 2)
+ .arg(e->posF().y(), 0, 'f', 2)
+ .arg(e->buttons())
+ .arg(e->pressure()*100, 0, 'f', 1)
+ ;
+
+ if(e->type() == QEvent::TabletMove) {
+ if(m_tabletDown) {
+ msg += " (DRAW)";
+ m_tabletPath << e->pos();
+ update();
+ } else {
+ msg += " (HOVER)";
+ }
+ }
+
+ emit eventReport(msg);
+}
+
+#ifndef DESIGNER_PLUGIN
+}
+#endif
diff --git a/libs/ui/input/wintab/drawpile_tablettester/tablettest.h b/libs/ui/input/wintab/drawpile_tablettester/tablettest.h
new file mode 100644
index 0000000000..938503dd8c
--- /dev/null
+++ b/libs/ui/input/wintab/drawpile_tablettester/tablettest.h
@@ -0,0 +1,65 @@
+/*
+ Drawpile - a collaborative drawing program.
+
+ Copyright (C) 2017 Calle Laakkonen
+
+ Drawpile is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Drawpile is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Drawpile. If not, see .
+*/
+
+#ifndef TABLETTEST_WIDGET_H
+#define TABLETTEST_WIDGET_H
+
+#include
+
+#ifndef DESIGNER_PLUGIN
+namespace widgets {
+#define PLUGIN_EXPORT
+#else
+#include
+#define PLUGIN_EXPORT QDESIGNER_WIDGET_EXPORT
+#endif
+
+class PLUGIN_EXPORT TabletTester : public QWidget {
+ Q_OBJECT
+public:
+ TabletTester(QWidget *parent=nullptr);
+
+public slots:
+ void clear();
+
+signals:
+ void eventReport(const QString &msg);
+
+protected:
+ void paintEvent(QPaintEvent *e) override;
+ void mousePressEvent(QMouseEvent *e) override;
+ void mouseMoveEvent(QMouseEvent *e) override;
+ void mouseReleaseEvent(QMouseEvent *e) override;
+ void tabletEvent(QTabletEvent *e) override;
+
+private:
+ QPolygon m_mousePath;
+ QPolygon m_tabletPath;
+
+ bool m_mouseDown;
+ bool m_tabletDown;
+};
+
+#ifndef DESIGNER_PLUGIN
+}
+#endif
+
+
+#endif
+
diff --git a/libs/ui/input/wintab/drawpile_tablettester/tablettest.ui b/libs/ui/input/wintab/drawpile_tablettester/tablettest.ui
new file mode 100644
index 0000000000..01772a5ec7
--- /dev/null
+++ b/libs/ui/input/wintab/drawpile_tablettester/tablettest.ui
@@ -0,0 +1,99 @@
+
+
+ TabletTest
+
+
+
+ 0
+ 0
+ 730
+ 385
+
+
+
+ Tablet Tester
+
+
+ -
+
+
+ -
+
+
-
+
+
+ true
+
+
+
+ -
+
+
+ Clear
+
+
+
+
+
+
+
+
+
+ TabletTester
+ QWidget
+
+ 1
+
+
+
+
+
+ pushButton
+ clicked()
+ logView
+ clear()
+
+
+ 722
+ 377
+
+
+ 659
+ 84
+
+
+
+
+ pushButton
+ clicked()
+ tablettest
+ clear()
+
+
+ 419
+ 359
+
+
+ 142
+ 242
+
+
+
+
+ tablettest
+ eventReport(QString)
+ logView
+ appendPlainText(QString)
+
+
+ 287
+ 187
+
+
+ 546
+ 207
+
+
+
+
+
diff --git a/libs/ui/input/wintab/drawpile_tablettester/tablettester.cpp b/libs/ui/input/wintab/drawpile_tablettester/tablettester.cpp
new file mode 100644
index 0000000000..d85d51e63d
--- /dev/null
+++ b/libs/ui/input/wintab/drawpile_tablettester/tablettester.cpp
@@ -0,0 +1,52 @@
+/*
+ Drawpile - a collaborative drawing program.
+
+ Copyright (C) 2017 Calle Laakkonen
+
+ Drawpile is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Drawpile is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Drawpile. If not, see .
+*/
+
+#include "tablettester.h"
+#include "widgets/tablettest.h"
+using widgets::TabletTester; // work around missing namespace in UIC generated code
+#include "ui_tablettest.h"
+
+#include "../main.h"
+
+namespace dialogs {
+
+TabletTestDialog::TabletTestDialog( QWidget *parent) :
+ QDialog(parent)
+{
+ m_ui = new Ui_TabletTest;
+ m_ui->setupUi(this);
+
+ connect(static_cast(qApp), &DrawpileApp::eraserNear, this, [this](bool near) {
+ QString msg;
+ if(near)
+ msg = QStringLiteral("Eraser brought near");
+ else
+ msg = QStringLiteral("Eraser taken away");
+
+ m_ui->logView->appendPlainText(msg);
+ });
+}
+
+TabletTestDialog::~TabletTestDialog()
+{
+ delete m_ui;
+}
+
+}
+
diff --git a/libs/ui/input/wintab/drawpile_tablettester/tablettester.h b/libs/ui/input/wintab/drawpile_tablettester/tablettester.h
new file mode 100644
index 0000000000..1f7cb718bc
--- /dev/null
+++ b/libs/ui/input/wintab/drawpile_tablettester/tablettester.h
@@ -0,0 +1,43 @@
+/*
+ Drawpile - a collaborative drawing program.
+
+ Copyright (C) 2017 Calle Laakkonen
+
+ Drawpile is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Drawpile is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Drawpile. If not, see .
+*/
+#ifndef TABLETTESTDIALOG_H
+#define TABLETTESTDIALOG_H
+
+#include
+
+class Ui_TabletTest;
+
+namespace dialogs {
+
+class TabletTestDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ TabletTestDialog(QWidget *parent=nullptr);
+ ~TabletTestDialog();
+
+private:
+ Ui_TabletTest *m_ui;
+
+};
+
+}
+
+#endif
+