aboutsummaryrefslogtreecommitdiffstats
path: root/tests/manual/x11vkbtest
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/x11vkbtest')
-rw-r--r--tests/manual/x11vkbtest/colors.h43
-rw-r--r--tests/manual/x11vkbtest/filehelper.cpp94
-rw-r--r--tests/manual/x11vkbtest/filehelper.h46
-rw-r--r--tests/manual/x11vkbtest/main.cpp105
-rw-r--r--tests/manual/x11vkbtest/memorymonitor.cpp226
-rw-r--r--tests/manual/x11vkbtest/memorymonitor.h90
-rw-r--r--tests/manual/x11vkbtest/mousesimulator.cpp367
-rw-r--r--tests/manual/x11vkbtest/mousesimulator.h73
-rw-r--r--tests/manual/x11vkbtest/processhandler.cpp82
-rw-r--r--tests/manual/x11vkbtest/processhandler.h65
-rw-r--r--tests/manual/x11vkbtest/startclose.cpp121
-rw-r--r--tests/manual/x11vkbtest/startclose.h60
-rw-r--r--tests/manual/x11vkbtest/testbase.cpp90
-rw-r--r--tests/manual/x11vkbtest/testbase.h74
-rw-r--r--tests/manual/x11vkbtest/testenglishletters.cpp138
-rw-r--r--tests/manual/x11vkbtest/testenglishletters.h65
-rw-r--r--tests/manual/x11vkbtest/testlanguagechange.cpp267
-rw-r--r--tests/manual/x11vkbtest/testlanguagechange.h66
-rw-r--r--tests/manual/x11vkbtest/testreporter.cpp159
-rw-r--r--tests/manual/x11vkbtest/testreporter.h53
-rw-r--r--tests/manual/x11vkbtest/testthread.cpp135
-rw-r--r--tests/manual/x11vkbtest/testthread.h59
-rw-r--r--tests/manual/x11vkbtest/windowhelper.cpp81
-rw-r--r--tests/manual/x11vkbtest/windowhelper.h55
-rw-r--r--tests/manual/x11vkbtest/x11vkbtest.pro41
25 files changed, 2655 insertions, 0 deletions
diff --git a/tests/manual/x11vkbtest/colors.h b/tests/manual/x11vkbtest/colors.h
new file mode 100644
index 00000000..ad1d5a0e
--- /dev/null
+++ b/tests/manual/x11vkbtest/colors.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COLORS_H
+#define COLORS_H
+
+namespace {
+#define RST "\x1B[0m"
+#define KRed "\x1B[31m"
+#define KGreen "\x1B[32m"
+
+#define FRed(x) KRed x RST
+#define FGreen(x) KGreen x RST
+#define FBold(x) "\x1B[1m" x RST
+};
+
+#endif // COLORS_H
diff --git a/tests/manual/x11vkbtest/filehelper.cpp b/tests/manual/x11vkbtest/filehelper.cpp
new file mode 100644
index 00000000..f3a379af
--- /dev/null
+++ b/tests/manual/x11vkbtest/filehelper.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QFile>
+#include <QTextStream>
+#include <QLoggingCategory>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <fstream>
+
+#include "filehelper.h"
+
+Q_LOGGING_CATEGORY(lcFileHelper, "qt.virtualkeyboard.tests.manual.x11vkbtest.filehelper")
+
+bool FileHelper::fileExists(const QString &fileName)
+{
+ std::ifstream stream(fileName.toLatin1());
+ return stream.good();
+}
+
+
+QString FileHelper::getFileContext(const QString &fileName)
+{
+ QString result = "";
+ QFile file(fileName);
+
+ if (!(!file.open(QFile::ReadOnly | QFile::Text))) {
+ QTextStream in(&file);
+ result = in.readAll();
+ file.close();
+ }
+
+ return result;
+}
+
+bool FileHelper::getJsonFromFile(const QString &fileName, std::map<QString, QVariant> &jsonMap)
+{
+ bool result = true;
+
+ if (!fileExists(fileName)) {
+ qCDebug(lcFileHelper) << "File:" << fileName << "doesn't exist";
+ result = false;
+ } else {
+ QString jsonString = FileHelper::getFileContext(fileName);
+ QByteArray jsonBytes = jsonString.toLocal8Bit();
+
+ auto jsonDoc = QJsonDocument::fromJson(jsonBytes);
+
+ if (jsonDoc.isNull()) {
+ qCDebug(lcFileHelper) << "jsonDoc is Null";
+ result = false;
+ } else if (!jsonDoc.isObject()) {
+ qCDebug(lcFileHelper) << "jsonDoc is NOT an object";
+ result = false;
+ } else {
+ QJsonObject jsonObj = jsonDoc.object();
+
+ if (jsonObj.isEmpty()) {
+ qCDebug(lcFileHelper) << "jsonObj is Empty";
+ result = false;
+ } else {
+ auto jsonIter = jsonObj.constBegin();
+ jsonMap.insert({jsonIter.key(), jsonIter.value()});
+ }
+ }
+ }
+ return result;
+}
diff --git a/tests/manual/x11vkbtest/filehelper.h b/tests/manual/x11vkbtest/filehelper.h
new file mode 100644
index 00000000..cc65351c
--- /dev/null
+++ b/tests/manual/x11vkbtest/filehelper.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILEHELPER_H
+#define FILEHELPER_H
+
+#include <map>
+
+class QString;
+class QVariant;
+
+class FileHelper
+{
+public:
+ static bool fileExists(const QString &fileName);
+ static QString getFileContext(const QString &fileName);
+ static bool getJsonFromFile(const QString &fileName, std::map<QString, QVariant> &jsonMap);
+};
+
+#endif // FILEHELPER_H
diff --git a/tests/manual/x11vkbtest/main.cpp b/tests/manual/x11vkbtest/main.cpp
new file mode 100644
index 00000000..f248bd53
--- /dev/null
+++ b/tests/manual/x11vkbtest/main.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QDebug>
+#include <QCommandLineParser>
+#include <QStateMachine>
+#include <QtGui/QGuiApplication>
+#include <QtCharts/QChartView>
+#include <QtWidgets/QMainWindow>
+
+#include "processhandler.h"
+#include "windowhelper.h"
+#include "testenglishletters.h"
+#include "startclose.h"
+#include "memorymonitor.h"
+#include "testlanguagechange.h"
+#include "testthread.h"
+#include "testreporter.h"
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QApplication app(argc, argv);
+
+ QCommandLineParser parser;
+ parser.setApplicationDescription("X11VKB Testing application");
+ parser.addHelpOption();
+
+ parser.addOption({"exec", "Give absolute path to target <executable>. See README.md for usage instructions.", "directory"});
+
+ parser.addOption({"sc", "Give a number of how many times a start&close cycle is to be executed.", "number"});
+
+ parser.addOption({"ko", "Give a number of how many times a key operation test is to be executed.", "number"});
+
+ parser.addOption({"lc", "Give a number of how many times a language change test is to be executed.", "number"});
+
+ parser.process(app);
+
+ QString x11vkbPath = parser.value("exec");
+ if (x11vkbPath.isEmpty()) {
+ qWarning() << "Give absolute path to target executable, including the filename";
+ qWarning() << "Example: --exec <path_to_executable>.";
+ qWarning() << "See README.md for detailed usage instructions.";
+ return 1;
+ }
+
+ quint32 startCloseTest = static_cast<quint16>(parser.value("sc").toInt());
+ quint32 keyOperationTest = static_cast<quint16>(parser.value("ko").toInt());
+ quint32 langChangeTest = static_cast<quint16>(parser.value("lc").toInt());
+
+ QMainWindow window;
+ window.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
+ auto memoryMonitor = new MemoryMonitor(window);
+
+ memoryMonitor->legend()->hide();
+ QChartView chartView(memoryMonitor);
+ chartView.setRenderHint(QPainter::Antialiasing);
+
+ window.setCentralWidget(&chartView);
+ window.resize(900, 600);
+ window.show();
+ memoryMonitor->init();
+
+ TestReporter reporter;
+ reporter.startMemoryReport();
+ QObject::connect(memoryMonitor, &MemoryMonitor::memUsage, &reporter, &TestReporter::currentMemUsage);
+
+ auto testThread = new TestThread(x11vkbPath, startCloseTest, keyOperationTest, langChangeTest, &app);
+ QObject::connect(testThread, &TestThread::startMemoryMonitor, memoryMonitor, &MemoryMonitor::start);
+ QObject::connect(testThread, &TestThread::processID, memoryMonitor, &MemoryMonitor::setProcID);
+ QObject::connect(testThread, &TestThread::finished, testThread, &QObject::deleteLater);
+ QObject::connect(testThread, &TestThread::finished, memoryMonitor, &MemoryMonitor::stopChart);
+ QObject::connect(memoryMonitor, &MemoryMonitor::minAndPeakReport, &reporter, &TestReporter::printMemoryResultToCSV);
+ QObject::connect(testThread, &TestThread::finished, &app, &QApplication::quit);
+ testThread->start();
+
+ return app.exec();
+}
diff --git a/tests/manual/x11vkbtest/memorymonitor.cpp b/tests/manual/x11vkbtest/memorymonitor.cpp
new file mode 100644
index 00000000..db1b53b9
--- /dev/null
+++ b/tests/manual/x11vkbtest/memorymonitor.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "memorymonitor.h"
+
+#include <QtCharts/QAbstractAxis>
+#include <QtCharts/QSplineSeries>
+#include <QtCharts/QValueAxis>
+#include <QtCore/QRandomGenerator>
+#include <QLoggingCategory>
+
+#include <QMainWindow>
+#include <QWindow>
+#include <QScreen>
+#include <QDir>
+
+#include <QTime>
+
+extern "C" {
+#include <unistd.h>
+#include <sys/resource.h>
+}
+#include <cstdio>
+
+namespace {
+const QString KChartFileName = "MemoryUsageChart";
+const quint8 KYPosition = 15;
+const quint8 KReadingMargin = 80;
+const quint16 KToKilo = 1024;
+}
+
+Q_LOGGING_CATEGORY(lcMemoryMonitor, "qt.virtualkeyboard.tests.manual.x11vkbtest.memorymonitor")
+
+MemoryMonitor::MemoryMonitor(QMainWindow &window, QGraphicsItem *parent, Qt::WindowFlags wFlags) :
+ QChart(QChart::ChartTypeCartesian, parent, wFlags),
+ m_series(nullptr),
+ m_axisX(new QValueAxis()),
+ m_axisY(new QValueAxis()),
+ m_x(0),
+ m_y(0),
+ m_peakMemory(0),
+ m_minMemory(0),
+ m_procID(0),
+ m_MainWindow(window),
+ m_screen(nullptr),
+ m_drawInterval(new QTimer()),
+ m_elapsedTime(0),
+ m_minMemReading(nullptr),
+ m_curMemReading(nullptr),
+ m_peakMemReading(nullptr),
+ m_elapsedTimeReading(nullptr)
+{
+ m_series = new QSplineSeries(this);
+ QPen red(Qt::red);
+ red.setWidth(3);
+ m_series->setPen(red);
+
+ this->addSeries(m_series);
+
+ this->addAxis(m_axisX,Qt::AlignBottom);
+ m_axisX->setTitleText("Time");
+ this->addAxis(m_axisY,Qt::AlignLeft);
+ m_axisY->setTitleText("Memory KB");
+ m_series->attachAxis(m_axisX);
+ m_series->attachAxis(m_axisY);
+ m_axisX->setTickCount(15);
+ m_axisX->setLabelFormat("%.1u");
+ m_axisY->setTickCount(15);
+ m_axisY->setLabelFormat("%.1u");
+ m_axisX->setRange(0, 500);
+ m_axisY->setRange(0, 100 * KToKilo);
+}
+
+void MemoryMonitor::init()
+{
+ QWindow *win = m_MainWindow.windowHandle();
+ m_screen = win->screen();
+
+ m_minMemReading = new QGraphicsSimpleTextItem(this);
+ m_minMemReading->setPen(QPen(QBrush("black"), 1));
+ m_minMemReading->setText("Min mem ----- KB");
+ m_minMemReading->setPos(KReadingMargin, KYPosition);
+
+ m_curMemReading = new QGraphicsSimpleTextItem(this);
+ m_curMemReading->setPen(QPen(QBrush("black"), 1));
+ m_curMemReading->setText("Current mem ----- KB");
+ m_curMemReading->setPos((this->size().width() / 2) - KReadingMargin, KYPosition);
+
+ m_peakMemReading = new QGraphicsSimpleTextItem(this);
+ m_peakMemReading->setPen(QPen(QBrush("black"), 1));
+ m_peakMemReading->setText("Peak mem ----- KB");
+ m_peakMemReading->setPos(this->size().width() - (KReadingMargin * 2), KYPosition);
+
+ m_elapsedTimeReading = new QGraphicsSimpleTextItem(this);
+ m_elapsedTimeReading->setPen(QPen(QBrush("black"), 1));
+ m_elapsedTimeReading->setText("-- s");
+ m_elapsedTimeReading->setPos((this->size().width() / 2) + KReadingMargin, this->size().height() - KYPosition * 3);
+
+ QObject::connect(this, &QChart::geometryChanged, [this]() {
+ m_minMemReading->setPos(KReadingMargin, KYPosition);
+ m_curMemReading->setPos((this->size().width() / 2) - KReadingMargin, KYPosition);
+ m_peakMemReading->setPos(this->size().width() - (KReadingMargin * 2), KYPosition);
+ m_elapsedTimeReading->setPos((this->size().width() / 2) + KReadingMargin, this->size().height() - KYPosition * 3);
+ });
+}
+
+void MemoryMonitor::setProcID(const qint64 procID)
+{
+ m_procID = procID;
+}
+
+void MemoryMonitor::start()
+{
+ QObject::connect(m_drawInterval, &QTimer::timeout, [&]() {
+ ulong memUsed = currentMemUsage();
+ this->drawMemUsage(memUsed);
+ this->storeMemValues(memUsed);
+ });
+ m_drawInterval->setInterval(1000);
+ m_drawInterval->start();
+}
+
+/**
+ * @brief currentMemUsage
+ * @param procID
+ * @return current memory by procID in kB
+ * Getting memory usage of a given process using
+ * Linux proc filesystem.
+ */
+ulong MemoryMonitor::currentMemUsage()
+{
+ ulong memSize = 0UL;
+ QString str = QString("/proc/" + QString::number(m_procID) + "/statm");
+ QFile procFile(str);
+
+ if (procFile.open(QIODevice::ReadOnly)) {
+ QTextStream procStream(&procFile);
+ ulong mem = procStream.readLine().split(" ").at(1).toULong();
+ memSize = mem * static_cast<ulong>(sysconf(_SC_PAGESIZE));
+ procFile.close();
+ }
+ auto result = memSize / KToKilo;
+ qCDebug(lcMemoryMonitor).noquote() << QTime::currentTime().toString() << "memory usage:" << result;
+
+ emit memUsage(m_elapsedTime, result);
+
+ return result;
+}
+
+MemoryMonitor::~MemoryMonitor()
+{
+ qCDebug(lcMemoryMonitor) << "Destroying MemoryChart";
+}
+
+void MemoryMonitor::saveChart()
+{
+ QPixmap pix = m_screen->grabWindow(m_MainWindow.winId());
+
+ const QString format = "png";
+ QString path = QDir::currentPath();
+ path += "/" + KChartFileName + "." + format;
+ pix.save(path);
+}
+
+void MemoryMonitor::stopChart()
+{
+ this->saveChart();
+ m_drawInterval->stop();
+
+ emit minAndPeakReport(QString("Min process memory: %1 KB\nPeak process memory: %2 KB")
+ .arg(QString::number(m_minMemory))
+ .arg(QString::number(m_peakMemory)));
+}
+
+void MemoryMonitor::storeMemValues(const ulong memValue)
+{
+ if ((m_minMemory == 0 || m_minMemory > memValue)) {
+ m_minMemory = memValue;
+ }
+ if (m_peakMemory < memValue) {
+ m_peakMemory = memValue;
+ }
+ m_minMemReading->setText(QString("Min mem %1 KB").arg(QString::number(m_minMemory)));
+ m_curMemReading->setText(QString("Current mem %1 KB").arg(QString::number(memValue)));
+ m_peakMemReading->setText(QString("Peak mem %1 KB").arg(QString::number(m_peakMemory)));
+ m_elapsedTimeReading->setText(QString("%1 s").arg(m_elapsedTime += 1));
+}
+
+void MemoryMonitor::drawMemUsage(const ulong memUsed)
+{
+ m_x += 1;
+ m_y = memUsed;
+ if (m_y >= m_axisY->max()) {
+ m_axisY->setRange(0, (m_axisY->max() * 2));
+ }
+ if (m_x >= m_axisX->max()) {
+ m_axisX->setRange(0, (m_axisX->max() * 2));
+ }
+ m_series->append(m_x, m_y);
+}
diff --git a/tests/manual/x11vkbtest/memorymonitor.h b/tests/manual/x11vkbtest/memorymonitor.h
new file mode 100644
index 00000000..01239383
--- /dev/null
+++ b/tests/manual/x11vkbtest/memorymonitor.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MEMORYMONITOR_H
+#define MEMORYMONITOR_H
+
+#include <QtCharts/QChart>
+#include <QtCore/QTimer>
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QSplineSeries;
+class QValueAxis;
+QT_CHARTS_END_NAMESPACE
+
+QT_CHARTS_USE_NAMESPACE
+
+class QMainWindow;
+
+class MemoryMonitor : public QChart
+{
+ Q_OBJECT
+public:
+ explicit MemoryMonitor(QMainWindow &window, QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = nullptr);
+ ~MemoryMonitor();
+
+public:
+ void init();
+ void start();
+ void drawMemUsage(const ulong memUsed);
+ void setProcID(const qint64 procID);
+
+signals:
+ void memUsage(const quint64 timeElapsed, const ulong memSize);
+ void minAndPeakReport(const QString minPeakMemoryReport);
+
+public slots:
+ void saveChart();
+ void stopChart();
+
+private:
+ ulong currentMemUsage();
+ void storeMemValues(const ulong memValue);
+
+private:
+ QSplineSeries *m_series;
+ QStringList m_titles;
+ QValueAxis *m_axisX;
+ QValueAxis *m_axisY;
+ ulong m_x;
+ ulong m_y;
+ ulong m_peakMemory;
+ ulong m_minMemory;
+ qint64 m_procID;
+ QMainWindow &m_MainWindow;
+ QScreen *m_screen;
+ QTimer *m_drawInterval;
+ quint64 m_elapsedTime;
+ QGraphicsSimpleTextItem *m_minMemReading;
+ QGraphicsSimpleTextItem *m_curMemReading;
+ QGraphicsSimpleTextItem *m_peakMemReading;
+ QGraphicsSimpleTextItem *m_elapsedTimeReading;
+};
+
+#endif // MEMORYMONITOR_H
diff --git a/tests/manual/x11vkbtest/mousesimulator.cpp b/tests/manual/x11vkbtest/mousesimulator.cpp
new file mode 100644
index 00000000..f49a91ef
--- /dev/null
+++ b/tests/manual/x11vkbtest/mousesimulator.cpp
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QTextStream>
+
+#include "mousesimulator.h"
+
+extern "C" {
+#include <xdo.h>
+#include <X11/X.h>
+#include <X11/extensions/XTest.h>
+#include <X11/keysym.h>
+#include <X11/XF86keysym.h>
+}
+#include <unistd.h>
+
+namespace {
+const quint16 KTime_Wait_After_Click = 50000;
+const quint16 KMultiply_Time_Wait_For_Shift_Key = 12;
+const quint16 KWidth_Parts = 24;
+const quint16 KHeight_Parts = 11;
+const quint16 KTotal_Lang_Rows = 5;
+}
+
+MouseSimulator::MouseSimulator(QObject *parent, Window x11vkbWinId, quint16 x11vkbWidth, quint16 x11vkbHeight) :
+ QObject(parent),
+ m_xdo(xdo_new(nullptr)),
+ m_x11vkbWinId(x11vkbWinId),
+ m_x11vkbWidth(x11vkbWidth),
+ m_x11vkbHeight(x11vkbHeight)
+{
+}
+
+/**
+ * @brief MouseSimulator::~MouseSimulator
+ */
+MouseSimulator::~MouseSimulator()
+{
+ xdo_free(m_xdo);
+}
+
+void MouseSimulator::mouseLeftClickOnVkb(QPair<quint16, quint16> coordinates) const
+{
+ xdo_move_mouse_relative_to_window(m_xdo, m_x11vkbWinId, 0, 0);
+ Display *dpy = m_xdo->xdpy;
+ XEvent event;
+
+ XQueryPointer(dpy, RootWindow(dpy,0), &event.xbutton.root,
+ &event.xbutton.window, &event.xbutton.x_root,
+ &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y,
+ &event.xbutton.state);
+
+ XTestFakeMotionEvent (dpy, 0, event.xbutton.x + coordinates.first,
+ event.xbutton.y + coordinates.second, CurrentTime);
+ XSync(dpy, 0);
+
+ XTestFakeButtonEvent(dpy, Button1, True, CurrentTime);
+ XTestFakeButtonEvent(dpy, Button1, False, CurrentTime);
+ XFlush(dpy);
+ usleep(KTime_Wait_After_Click);
+}
+
+void MouseSimulator::setWidthHeight(QPair<quint16, quint16> pairWidthHeight)
+{
+ m_x11vkbWidth = pairWidthHeight.first;
+ m_x11vkbHeight = pairWidthHeight.first;
+}
+
+void MouseSimulator::clickCtrlPlusSToSave(const Window winId) const
+{
+ xdo_move_mouse_relative_to_window(m_xdo, winId, 5, 5);
+ Display *dpy = m_xdo->xdpy;
+ XTestFakeKeyEvent(dpy, XKeysymToKeycode( dpy, XK_Control_L ), true, CurrentTime);
+ XTestFakeKeyEvent(dpy, XKeysymToKeycode( dpy, XK_S ), true, CurrentTime);
+ XTestFakeKeyEvent(dpy, XKeysymToKeycode( dpy, XK_S ), false, CurrentTime);
+ XTestFakeKeyEvent(dpy, XKeysymToKeycode( dpy, XK_Control_L ), false, CurrentTime);
+ XFlush(dpy);
+}
+
+void MouseSimulator::clickLangKey(const quint16 layoutEnglish) const
+{
+ if (layoutEnglish == 2) {
+ mouseLeftClickOnVkb(getPositionOfNotEngLayout(4,2));
+ } else {
+ mouseLeftClickOnVkb(getPosition(4,2));
+ }
+}
+
+void MouseSimulator::clickLangLine(const LanguageLines langLine) const
+{
+ quint16 width = m_x11vkbWidth/KTotal_Lang_Rows;
+ quint16 height = m_x11vkbHeight/KHeight_Parts;
+ switch (langLine) {
+ case LanguageLines::FirstLine:
+ height = height*4;
+ break;
+ case LanguageLines::SecondLine:
+ height = height*5;
+ break;
+ case LanguageLines::ThirdLine:
+ height = height*6;
+ break;
+ case LanguageLines::FourthLine:
+ height = height*7;
+ break;
+ case LanguageLines::FifthLine:
+ height = height*8;
+ break;
+ }
+ mouseLeftClickOnVkb({width, height});
+}
+
+void MouseSimulator::clickHideKeyboard() const
+{
+ mouseLeftClickOnVkb(getPosition(4,6));
+}
+
+QPair<quint16, quint16> MouseSimulator::getPosition(const quint16 rowNum, const quint16 keyNum) const
+{
+ QPair<quint16, quint16> coordinates(0,0);
+
+ if (0 < rowNum && rowNum <= 4) {
+ coordinates.second = this->vkbPositionOfRow(rowNum);
+ switch (rowNum)
+ {
+ case 1:
+ case 3:
+ if (0 < keyNum && keyNum <= 11) {
+ coordinates.first = m_x11vkbWidth/KWidth_Parts*(keyNum*2);
+ }
+ break;
+ case 2:
+ if (0 < keyNum && keyNum <= 10) {
+ coordinates.first = m_x11vkbWidth/KWidth_Parts*(keyNum*2+1);
+ }
+ break;
+ case 4:
+ switch (keyNum) {
+ case 1:
+ coordinates.first = m_x11vkbWidth/KWidth_Parts*(keyNum*2);
+ break;
+ case 2:
+ coordinates.first = m_x11vkbWidth/KWidth_Parts*5;
+ break;
+ case 3:
+ coordinates.first = m_x11vkbWidth/2;
+ break;
+ case 4:
+ coordinates.first = m_x11vkbWidth/KWidth_Parts*18;
+ break;
+ case 5:
+ coordinates.first = m_x11vkbWidth/KWidth_Parts*20;
+ break;
+ case 6:
+ coordinates.first = m_x11vkbWidth/KWidth_Parts*(KWidth_Parts-2);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return coordinates;
+}
+
+QPair<quint16, quint16> MouseSimulator::getPositionOfNotEngLayout(const quint16 rowNum, const quint16 keyNum) const
+{
+ QPair<quint16, quint16> coordinates(0, vkbPositionOfRow(rowNum));
+ if (rowNum == 4 && keyNum == 2) {
+ coordinates.first = m_x11vkbWidth/KWidth_Parts*4;
+ }
+ return coordinates;
+}
+
+void MouseSimulator::clickLetter(const QChar &letter) const
+{
+ switch (letter.toLower().unicode())
+ {
+ case 'a':
+ mouseLeftClickOnVkb(this->getPosition(2,1));
+ break;
+ case 'b':
+ mouseLeftClickOnVkb(this->getPosition(3,6));
+ break;
+ case 'c':
+ mouseLeftClickOnVkb(this->getPosition(3,4));
+ break;
+ case 'd':
+ mouseLeftClickOnVkb(this->getPosition(2,3));
+ break;
+ case 'e':
+ mouseLeftClickOnVkb(this->getPosition(1,3));
+ break;
+ case 'f':
+ mouseLeftClickOnVkb(this->getPosition(2,4));
+ break;
+ case 'g':
+ mouseLeftClickOnVkb(this->getPosition(2,5));
+ break;
+ case 'h':
+ mouseLeftClickOnVkb(this->getPosition(2,6));
+ break;
+ case 'i':
+ mouseLeftClickOnVkb(this->getPosition(1,8));
+ break;
+ case 'j':
+ mouseLeftClickOnVkb(this->getPosition(2,7));
+ break;
+ case 'k':
+ mouseLeftClickOnVkb(this->getPosition(2,8));
+ break;
+ case 'l':
+ mouseLeftClickOnVkb(this->getPosition(2,9));
+ break;
+ case 'm':
+ mouseLeftClickOnVkb(this->getPosition(3,8));
+ break;
+ case 'n':
+ mouseLeftClickOnVkb(this->getPosition(3,7));
+ break;
+ case 'o':
+ mouseLeftClickOnVkb(this->getPosition(1,9));
+ break;
+ case 'p':
+ mouseLeftClickOnVkb(this->getPosition(1,10));
+ break;
+ case 'q':
+ mouseLeftClickOnVkb(this->getPosition(1,1));
+ break;
+ case 'r':
+ mouseLeftClickOnVkb(this->getPosition(1,4));
+ break;
+ case 's':
+ mouseLeftClickOnVkb(this->getPosition(2,2));
+ break;
+ case 't':
+ mouseLeftClickOnVkb(this->getPosition(1,5));
+ break;
+ case 'u':
+ mouseLeftClickOnVkb(this->getPosition(1,7));
+ break;
+ case 'v':
+ mouseLeftClickOnVkb(this->getPosition(3,5));
+ break;
+ case 'w':
+ mouseLeftClickOnVkb(this->getPosition(1,2));
+ break;
+ case 'x':
+ mouseLeftClickOnVkb(this->getPosition(3,3));
+ break;
+ case 'y':
+ mouseLeftClickOnVkb(this->getPosition(1,6));
+ break;
+ case 'z':
+ mouseLeftClickOnVkb(this->getPosition(3,2));
+ break;
+ default:
+ break;
+ }
+
+}
+
+void MouseSimulator::clickEnglishLetter(QChar &letter) const
+{
+ this->clickExtraKeyIfNeeded(letter);
+
+ if (letter.isLetter()) {
+ this->clickLetter(letter);
+ } else if (letter.isNumber()) {
+ quint16 number = static_cast<quint16>(letter.digitValue());
+ mouseLeftClickOnVkb(this->getPosition(1, number == 0 ? 10 : static_cast<quint16>(number) ));
+ } else {
+ switch (letter.unicode())
+ {
+ case ' ':
+ mouseLeftClickOnVkb(this->getPosition(4,3));
+ break;
+ case ',':
+ mouseLeftClickOnVkb(this->getPosition(3,9));
+ break;
+ case '.':
+ mouseLeftClickOnVkb(this->getPosition(3,10));
+ break;
+ case '\'':
+ mouseLeftClickOnVkb(this->getPosition(4,4));
+ break;
+ case '\b':
+ mouseLeftClickOnVkb(this->getPosition(1,11));
+ break;
+ case QChar::CarriageReturn :
+ mouseLeftClickOnVkb(this->getPosition(2,10));
+ break;
+ default:
+ break;
+ }
+ }
+
+ this->clickExtraKeyIfNeeded(letter);
+}
+
+void MouseSimulator::clickExtraKeyIfNeeded(QChar &letter) const
+{
+ bool clickIsNeeded = false;
+ if (letter.isUpper()) {
+ mouseLeftClickOnVkb(this->getPosition(3,1));
+ clickIsNeeded = true;
+ } else if (letter.isNumber()) {
+ mouseLeftClickOnVkb(this->getPosition(4,1));
+ clickIsNeeded = true;
+ }
+
+ if (clickIsNeeded) {
+ usleep(KTime_Wait_After_Click*KMultiply_Time_Wait_For_Shift_Key);
+ }
+}
+
+quint16 MouseSimulator::vkbPositionOfRow(const quint16 row) const
+{
+ quint16 heightSize = m_x11vkbHeight/KHeight_Parts;
+ switch (row)
+ {
+ case 1 :
+ heightSize = heightSize*3;
+ break;
+ case 2 :
+ heightSize = heightSize*5;
+ break;
+ case 3 :
+ heightSize = heightSize*7;
+ break;
+ case 4 :
+ heightSize = heightSize*9;
+ break;
+ default:
+ heightSize = 0;
+ break;
+ }
+ return heightSize;
+}
diff --git a/tests/manual/x11vkbtest/mousesimulator.h b/tests/manual/x11vkbtest/mousesimulator.h
new file mode 100644
index 00000000..7fdff58c
--- /dev/null
+++ b/tests/manual/x11vkbtest/mousesimulator.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MOUSESIMULATOR_H
+#define MOUSESIMULATOR_H
+
+#include <QObject>
+
+extern "C" {
+#include <xdo.h>
+}
+
+class MouseSimulator : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MouseSimulator(QObject *parent, Window x11vkbWinId, quint16 x11vkbWidth, quint16 x11vkbHeight);
+ ~MouseSimulator() override;
+
+public:
+ enum LanguageLines {FirstLine, SecondLine, ThirdLine, FourthLine, FifthLine};
+ void clickEnglishLetter(QChar &letter) const;
+ void clickExtraKeyIfNeeded(QChar &letter) const;
+ void clickCtrlPlusSToSave(const Window winId) const;
+ void clickLangKey(const quint16 layoutEnglish = 1) const;
+ void clickLangLine(const LanguageLines langLine) const;
+ void clickHideKeyboard() const;
+ void mouseLeftClickOnVkb(QPair<quint16, quint16> coordinates) const;
+ void setWidthHeight(QPair<quint16, quint16> pairWidthHeight);
+ QPair<quint16, quint16> getPosition(const quint16 rowNum, const quint16 keyNum) const;
+ QPair<quint16, quint16> getPositionOfNotEngLayout(const quint16 rowNum, const quint16 keyNum) const;
+
+private:
+ quint16 vkbPositionOfRow(const quint16 row) const;
+ void clickLetter(const QChar &letter) const;
+
+private:
+ /** Libxdo context. */
+ xdo_t *m_xdo;
+ Window m_x11vkbWinId;
+ quint16 m_x11vkbWidth;
+ quint16 m_x11vkbHeight;
+};
+
+
+#endif // MOUSESIMULATOR_H
+
diff --git a/tests/manual/x11vkbtest/processhandler.cpp b/tests/manual/x11vkbtest/processhandler.cpp
new file mode 100644
index 00000000..ca9c82c6
--- /dev/null
+++ b/tests/manual/x11vkbtest/processhandler.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QProcess>
+#include <QTextStream>
+
+#include <unistd.h>
+
+#include "processhandler.h"
+
+ProcessHandler::ProcessHandler(QObject *parent, const QString &procPath, quint32 msec) :
+ QObject(parent),
+ m_process(new QProcess(this)),
+ m_procPath(procPath),
+ m_msec(msec)
+{
+ m_process->setProgram(m_procPath);
+ QObject::connect(m_process, &QProcess::started, this, &ProcessHandler::procStarted);
+}
+
+ProcessHandler::~ProcessHandler()
+{
+ this->closeProcess();
+}
+
+qint64 ProcessHandler::getProcId() const
+{
+ return m_process->processId();
+}
+
+void ProcessHandler::closeProcess()
+{
+ m_process->close();
+}
+
+void ProcessHandler::procStarted()
+{
+ if (m_msec > 0) {
+ usleep(m_msec);
+ }
+ emit procReady();
+}
+
+void ProcessHandler::startProc()
+{
+ m_process->start(m_procPath);
+}
+
+void ProcessHandler::startDetachedProc() const
+{
+ m_process->startDetached(m_procPath);
+}
+
+QProcess* ProcessHandler::getPRocess() const {
+ return m_process;
+}
diff --git a/tests/manual/x11vkbtest/processhandler.h b/tests/manual/x11vkbtest/processhandler.h
new file mode 100644
index 00000000..c1d14983
--- /dev/null
+++ b/tests/manual/x11vkbtest/processhandler.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROCESSHANDLER_H
+#define PROCESSHANDLER_H
+
+#include <QObject>
+
+class QProcess;
+
+class ProcessHandler : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ProcessHandler(QObject *parent, const QString &procPath, quint32 msec = 0);
+ ~ProcessHandler();
+
+public:
+ void startProc();
+ qint64 getProcId() const;
+ QProcess *getPRocess() const;
+ void startDetachedProc() const;
+
+signals:
+ void procReady();
+
+public slots:
+ void closeProcess();
+
+private slots:
+ void procStarted();
+
+private:
+ QProcess *m_process;
+ const QString &m_procPath;
+ quint32 m_msec;
+};
+
+#endif // PROCESSHANDLER_H
diff --git a/tests/manual/x11vkbtest/startclose.cpp b/tests/manual/x11vkbtest/startclose.cpp
new file mode 100644
index 00000000..2738dc26
--- /dev/null
+++ b/tests/manual/x11vkbtest/startclose.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QProcess>
+#include <QFile>
+#include <QTextStream>
+#include <QTimer>
+
+#include "startclose.h"
+
+namespace {
+const QString KTest_Name = "Test start/close %1 times.";
+const quint16 KTestCycles = 25;
+const int KTestMultiplier = 2;
+}
+
+StartClose::StartClose(QProcess &proc, quint32 numberOfTests, QObject *parent)
+ : TestBase (parent, KTest_Name, numberOfTests),
+ m_procToTest(proc),
+ m_results(QStringList()),
+ m_testCycleCount(0)
+{
+ this->setTestRepeats(KTestCycles);
+ this->setTestName();
+ QObject::connect(&m_procToTest, &QProcess::started, this, &StartClose::runCycles);
+ QObject::connect(&m_procToTest, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ this, &StartClose::runCycles);
+}
+
+void StartClose::startTest()
+{
+ m_testTimer.start();
+ m_procToTest.start();
+}
+
+void StartClose::runCycles()
+{
+ QTimer::singleShot(50, this, [&]() {
+ if (m_testCycleCount == 0) {
+ m_results << QString::number(this->currentTotalAvailableMemory());
+ }
+ // The original number of tests will be multiplied by 2 because we always need to
+ // have even number of test cycles because one cycle consists off ON & OFF.
+ if (m_testCycleCount == (m_numberOfTests * KTestMultiplier)) {
+ m_results << QString::number(this->currentTotalAvailableMemory());
+ QObject::disconnect(&m_procToTest, &QProcess::started, this, &StartClose::startTest);
+ QObject::disconnect(&m_procToTest,
+ static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ this, &StartClose::startTest);
+
+ m_passed = true;
+ m_timeElapsed = m_testTimer.elapsed();
+
+ emit endTest();
+ return;
+ }
+ m_testCycleCount ++;
+
+ if (m_procToTest.state() == QProcess::Running) {
+ m_procToTest.kill();
+ } else {
+ m_procToTest.start();
+ }
+ });
+}
+
+QString StartClose::reportResult()
+{
+ m_testResult =
+ QString("Total free system memory at start: %1 KB\nTotal free system memory at end: %2 KB\nDifference: %3 KB")
+ .arg(m_results.value(0).toInt()).arg(m_results.value(1).toInt())
+ .arg(m_results.value(1).toInt() - m_results.value(0).toInt());
+ return m_testResult;
+}
+
+/**
+ * @brief StartClose::currentTotalAvailableMemory
+ * @return current free system memory by procID in kB
+ * Getting current free memory using Linux proc
+ * filesystem.
+ */
+ulong StartClose::currentTotalAvailableMemory() const
+{
+ ulong availableMemSize = 0UL;
+ QString str = QString("/proc/meminfo");
+ QFile procFile(str);
+
+ if (procFile.open(QIODevice::ReadOnly)) {
+ QTextStream procStream(&procFile);
+ procStream.readLine(); // "Read away" the first row
+ availableMemSize = procStream.readLine().split(QRegExp("\\s+")).at(1).toULong();
+ procFile.close();
+ }
+ return availableMemSize;
+}
diff --git a/tests/manual/x11vkbtest/startclose.h b/tests/manual/x11vkbtest/startclose.h
new file mode 100644
index 00000000..434a95ad
--- /dev/null
+++ b/tests/manual/x11vkbtest/startclose.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef STARTCLOSE_H
+#define STARTCLOSE_H
+
+#include "testbase.h"
+
+#include <QTime>
+
+class QProcess;
+
+class StartClose : public TestBase
+{
+ Q_OBJECT
+public:
+ explicit StartClose(QProcess &proc, quint32 numberOfTests, QObject *parent = nullptr);
+ ~StartClose() {}
+
+public:
+ ulong currentTotalAvailableMemory() const;
+ QString reportResult() override;
+
+public slots:
+ void startTest() override;
+ void runCycles();
+
+private:
+ QProcess &m_procToTest;
+ QStringList m_results;
+ quint32 m_testCycleCount;
+};
+
+#endif // STARTCLOSE_H
diff --git a/tests/manual/x11vkbtest/testbase.cpp b/tests/manual/x11vkbtest/testbase.cpp
new file mode 100644
index 00000000..ef08c8c6
--- /dev/null
+++ b/tests/manual/x11vkbtest/testbase.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QTextStream>
+#include "testbase.h"
+
+namespace {
+const qint32 KMs_In_Sec = 1000;
+}
+
+TestBase::TestBase(QObject *parent, QString testName, quint32 numberOfTests, qint64 x11vkbProcId):
+ QObject(parent),
+ m_x11vkbProcId(x11vkbProcId),
+ m_testTimer(QElapsedTimer()),
+ m_timeElapsed(0),
+ m_testName(testName),
+ m_numberOfTests(numberOfTests),
+ m_testResult(QString()),
+ m_passed(false)
+
+{}
+
+QString TestBase::reportResult()
+{
+ return m_testResult;
+}
+
+void TestBase::setProcID(const qint64 procID)
+{
+ m_x11vkbProcId = procID;
+}
+
+QString TestBase::testName() const
+{
+ return m_testName;
+}
+
+void TestBase::setTestName()
+{
+ m_testName = m_testName.arg(m_numberOfTests);
+}
+void TestBase::printResult(QTextStream &stream) const
+{
+ stream << m_testResult;
+}
+
+bool TestBase::passed() const
+{
+ return m_passed;
+}
+
+qint64 TestBase::timeElapsed() const
+{
+ return m_timeElapsed/KMs_In_Sec;
+}
+
+bool TestBase::shiftIsDown = false;
+
+void TestBase::setTestRepeats(const quint32 repeats)
+{
+ if (m_numberOfTests == 0) {
+ m_numberOfTests = repeats;
+ }
+}
diff --git a/tests/manual/x11vkbtest/testbase.h b/tests/manual/x11vkbtest/testbase.h
new file mode 100644
index 00000000..0b5c107b
--- /dev/null
+++ b/tests/manual/x11vkbtest/testbase.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESTBASE_H
+#define TESTBASE_H
+
+#include <QObject>
+#include <QElapsedTimer>
+
+class QTextStream;
+
+class TestBase : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit TestBase(QObject *parent, QString testName, quint32 numberOfTests, qint64 x11vkbProcId = 0);
+ virtual ~TestBase() {}
+
+public:
+ virtual QString reportResult();
+ void setProcID(const qint64 procID);
+ QString testName() const;
+ void setTestName();
+ void printResult(QTextStream &stream) const;
+ bool passed() const;
+ qint64 timeElapsed() const;
+ void setTestRepeats(const quint32 repeats);
+
+signals:
+ void endTest();
+
+public slots:
+ virtual void startTest() = 0;
+
+protected:
+ static bool shiftIsDown;
+ qint64 m_x11vkbProcId;
+ QElapsedTimer m_testTimer;
+
+ qint64 m_timeElapsed;
+ QString m_testName;
+ quint32 m_numberOfTests;
+ QString m_testResult;
+ bool m_passed;
+};
+
+#endif // TESTBASE_H
diff --git a/tests/manual/x11vkbtest/testenglishletters.cpp b/tests/manual/x11vkbtest/testenglishletters.cpp
new file mode 100644
index 00000000..c0f63e53
--- /dev/null
+++ b/tests/manual/x11vkbtest/testenglishletters.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "filehelper.h"
+#include "mousesimulator.h"
+#include "processhandler.h"
+#include "windowhelper.h"
+#include "testenglishletters.h"
+
+namespace {
+const QString KTest_Name = "Test %1 key operations.";
+
+const quint32 KTime_Wait_To_Start_Process = 350000;
+const quint32 KTime_Wait_To_Close_Process = 100000;
+const QString KTest_File_Name = "test_letters.txt";
+const QString KTest_String = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv\n";
+const quint16 KMax_Key_Operations = 100;
+}
+
+TestEnglishLetters::TestEnglishLetters(QObject *parent, WindowHelper &windowHelper, quint32 numberOfTests, qint64 x11vkbProcId) :
+ TestBase(parent, KTest_Name, numberOfTests, x11vkbProcId),
+ m_windowHelper(windowHelper),
+ m_otherProcHandler(nullptr),
+ m_letters(QString())
+{
+ this->setTestRepeats(KMax_Key_Operations);
+ this->setTestName();
+ this->setTestingString();
+}
+
+void TestEnglishLetters::startTest()
+{
+ m_testTimer.start();
+ this->deleteTestFile();
+
+ QString geditProcessName = QString("gedit -s %1").arg(KTest_File_Name);
+ m_otherProcHandler = new ProcessHandler(this, geditProcessName, KTime_Wait_To_Start_Process);
+
+ QObject::connect(m_otherProcHandler, &ProcessHandler::procReady, this, &TestEnglishLetters::doTestLettersInGedit);
+
+ m_otherProcHandler->startProc();
+}
+
+void TestEnglishLetters::doTestLettersInGedit()
+{
+ auto x11vkbWin = m_windowHelper.findWindowByPid(m_x11vkbProcId);
+ auto otherWinId = m_windowHelper.findWindowByPid(m_otherProcHandler->getProcId());
+
+ auto bigDimension = m_windowHelper.getWindowDimension(x11vkbWin);
+ auto mouseSimulator = new MouseSimulator(this, x11vkbWin, bigDimension.first, bigDimension.second);
+
+ QStringList lines = m_letters.split( QRegExp("[\n]") );
+ QChar enterChar = QChar::CarriageReturn;
+
+ // first click shiftKey to get it Down
+ if (!TestBase::shiftIsDown) {
+ mouseSimulator->mouseLeftClickOnVkb(mouseSimulator->getPosition(3,1));
+ TestBase::shiftIsDown = true;
+ }
+
+ for (auto line : lines)
+ {
+ for (auto letter : line)
+ {
+ mouseSimulator->clickEnglishLetter(letter);
+ }
+ if (line != lines.at(lines.size()-1)) {
+ mouseSimulator->clickEnglishLetter(enterChar);
+ }
+ }
+
+ // close gedit process starts
+ usleep(KTime_Wait_To_Close_Process);
+ mouseSimulator->clickCtrlPlusSToSave(otherWinId);
+ usleep(KTime_Wait_To_Close_Process);
+ m_otherProcHandler->closeProcess();
+
+ this->verifyResult();
+ this->deleteTestFile();
+
+ m_timeElapsed = m_testTimer.elapsed();
+
+ emit endTest();
+}
+
+void TestEnglishLetters::verifyResult()
+{
+ auto resultStr = FileHelper::getFileContext(KTest_File_Name);
+ if (QString::compare(m_letters, resultStr.trimmed() ) == 0) {
+ m_passed = true;
+ } else {
+ m_testResult =
+ QString("key operation amount expected: %1\nkey operation amount result: : %2")
+ .arg(m_letters.size()).arg(resultStr.size());
+ }
+}
+
+void TestEnglishLetters::deleteTestFile() const
+{
+ if (FileHelper::fileExists(KTest_File_Name)) {
+ std::remove(KTest_File_Name.toLatin1());
+ }
+}
+
+void TestEnglishLetters::setTestingString()
+{
+ QString testString = "";
+ while (testString.trimmed().size() < static_cast<int>(m_numberOfTests)) {
+ testString = testString + KTest_String;
+ }
+ m_letters = testString.mid(0, static_cast<int>(m_numberOfTests));
+}
diff --git a/tests/manual/x11vkbtest/testenglishletters.h b/tests/manual/x11vkbtest/testenglishletters.h
new file mode 100644
index 00000000..f39086de
--- /dev/null
+++ b/tests/manual/x11vkbtest/testenglishletters.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESTENGLISHLETTERS_H
+#define TESTENGLISHLETTERS_H
+
+#include <QObject>
+#include "testbase.h"
+
+class WindowHelper;
+class ProcessHandler;
+
+class TestEnglishLetters : public TestBase
+{
+ Q_OBJECT
+public:
+ explicit TestEnglishLetters(QObject *parent, WindowHelper &windowHelper, quint32 numberOfTests, qint64 x11vkbProcId = 0);
+ ~TestEnglishLetters() {}
+
+public:
+ void setTestingString();
+
+public slots:
+ void startTest() override;
+
+private slots:
+ void doTestLettersInGedit();
+
+private:
+ void verifyResult();
+ void deleteTestFile() const;
+
+private:
+ WindowHelper &m_windowHelper;
+ ProcessHandler *m_otherProcHandler;
+ QString m_letters;
+};
+
+#endif // TESTENGLISHLETTERS_H
diff --git a/tests/manual/x11vkbtest/testlanguagechange.cpp b/tests/manual/x11vkbtest/testlanguagechange.cpp
new file mode 100644
index 00000000..082c00a2
--- /dev/null
+++ b/tests/manual/x11vkbtest/testlanguagechange.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QLoggingCategory>
+#include <QFile>
+#include <QVector>
+#include <QTextStream>
+#include <QDir>
+#include <QElapsedTimer>
+
+#include "mousesimulator.h"
+#include "windowhelper.h"
+#include "testlanguagechange.h"
+#include "filehelper.h"
+#include "processhandler.h"
+
+namespace {
+const QString KTest_Name = "Test %1 language change operations.";
+
+const QString KFile_Path = "/x11vkbwrapper_language/";
+const QString KFile_Path_Name = KFile_Path + "currentLang.json";
+const quint32 KTime_Wait_After_Click = 180000;
+const quint32 KTime_Wait_To_Start_Process = 350000;
+const quint32 KTestRepeats = 10;
+
+const QVector< QPair< QString, quint8 > > KLanguage_List = {
+ QPair< QString, quint8 >("العربية", 1),
+ QPair< QString, quint8 >("български", 1),
+ QPair< QString, quint8 >("čeština", 1),
+ QPair< QString, quint8 >("dansk", 1),
+ QPair< QString, quint8 >("Deutsch", 1),
+ QPair< QString, quint8 >("Ελληνικά", 1),
+ QPair< QString, quint8 >("British English", 1),
+ QPair< QString, quint8 >("American English", 1),
+ QPair< QString, quint8 >("español de España", 1),
+ QPair< QString, quint8 >("español de México", 1),
+ QPair< QString, quint8 >("eesti", 1),
+ QPair< QString, quint8 >("فارسی", 1),
+ QPair< QString, quint8 >("suomi", 1),
+ QPair< QString, quint8 >("français canadien", 1),
+ QPair< QString, quint8 >("français", 1),
+ QPair< QString, quint8 >("עברית", 1),
+ QPair< QString, quint8 >("हिन्दी", 1),
+ QPair< QString, quint8 >("hrvatski", 1),
+ QPair< QString, quint8 >("magyar", 1),
+ QPair< QString, quint8 >("Indonesia", 1),
+ QPair< QString, quint8 >("italiano", 1),
+ QPair< QString, quint8 >("日本語", 2),
+ QPair< QString, quint8 >("한국어", 1),
+ QPair< QString, quint8 >("Melayu", 1),
+ QPair< QString, quint8 >("norsk bokmål", 1),
+ QPair< QString, quint8 >("Nederlands", 1),
+ QPair< QString, quint8 >("polski", 1),
+ QPair< QString, quint8 >("português", 1),
+ QPair< QString, quint8 >("português europeu", 1),
+ QPair< QString, quint8 >("română", 1),
+ QPair< QString, quint8 >("русский", 1),
+ QPair< QString, quint8 >("slovenčina", 1),
+ QPair< QString, quint8 >("slovenščina", 1),
+ QPair< QString, quint8 >("shqip", 1),
+ QPair< QString, quint8 >("српски", 1),
+ QPair< QString, quint8 >("svenska", 1),
+ QPair< QString, quint8 >("ไทย", 1),
+ QPair< QString, quint8 >("Türkçe", 1),
+ QPair< QString, quint8 >("українська", 1),
+ QPair< QString, quint8 >("Tiếng Việt", 1),
+ QPair< QString, quint8 >("简体中文", 1),
+ QPair< QString, quint8 >("繁體中文", 1)
+};
+}
+
+Q_LOGGING_CATEGORY(lcTestLanguageChange, "qt.virtualkeyboard.tests.manual.x11vkbtest.testlanguagechange")
+
+TestLanguageChange::TestLanguageChange(QObject *parent, WindowHelper &windowHelper, quint32 numberOfTests, qint64 x11vkbProcId) :
+ TestBase(parent, KTest_Name, numberOfTests, x11vkbProcId),
+ m_windowHelper(windowHelper),
+ m_otherProcHandler(nullptr),
+ m_currentLangNum(0)
+{
+ this->setTestRepeats(KTestRepeats);
+ this->setTestName();
+}
+
+void TestLanguageChange::startTest()
+{
+ m_testTimer.start();
+ this->deleteTestFile();
+
+ QString geditProcessName = QString("gedit -s");
+ m_otherProcHandler = new ProcessHandler(this, geditProcessName, KTime_Wait_To_Start_Process);
+
+ QObject::connect(m_otherProcHandler, &ProcessHandler::procReady, this, &TestLanguageChange::doTest);
+
+ m_otherProcHandler->startProc();
+}
+
+void TestLanguageChange::doTest()
+{
+ auto x11vkbWin = m_windowHelper.findWindowByPid(m_x11vkbProcId);
+
+ auto currentDimension = m_windowHelper.getWindowDimension(x11vkbWin);
+ auto mouseSimulator = new MouseSimulator(this, x11vkbWin, currentDimension.first, currentDimension.second);
+
+ // First click shiftKey to get it Down
+ if (!TestBase::shiftIsDown) {
+ mouseSimulator->mouseLeftClickOnVkb(mouseSimulator->getPosition(3,1));
+ TestBase::shiftIsDown = true;
+ }
+
+ quint32 count = 0;
+ quint8 langLayout = 0;
+ auto currentLangLine = MouseSimulator::LanguageLines::FourthLine;
+
+ // Determine the current language -->
+ mouseSimulator->clickLangKey(langLayout);
+ usleep(KTime_Wait_After_Click);
+ mouseSimulator->clickLangLine(currentLangLine);
+ usleep(KTime_Wait_After_Click);
+
+ langLayout = this->verifyLanguage(m_currentLangNum, false);
+
+ m_currentLangNum++;
+ if (m_currentLangNum == KLanguage_List.size()-1) {
+ currentLangLine = MouseSimulator::LanguageLines::FifthLine;
+ }
+ // <-- Determine the current language
+
+ bool indexIncreases = true;
+
+ while (count < m_numberOfTests && langLayout != 0) {
+ mouseSimulator->clickLangKey(langLayout);
+ usleep(KTime_Wait_After_Click);
+
+ mouseSimulator->clickLangLine(currentLangLine);
+ usleep(KTime_Wait_After_Click);
+
+ langLayout = this->verifyLanguage(m_currentLangNum);
+
+ count++;
+
+ switch (currentLangLine) {
+
+ case MouseSimulator::LanguageLines::FirstLine:
+ indexIncreases = true;
+ m_currentLangNum++;
+ currentLangLine = MouseSimulator::LanguageLines::SecondLine;
+ break;
+
+ case MouseSimulator::LanguageLines::SecondLine:
+ if (indexIncreases) {
+ m_currentLangNum++;
+ currentLangLine = MouseSimulator::LanguageLines::ThirdLine;
+ } else {
+ m_currentLangNum--;
+ if (m_currentLangNum == 0) {
+ currentLangLine = MouseSimulator::LanguageLines::FirstLine;
+ }
+ }
+ break;
+
+ case MouseSimulator::LanguageLines::ThirdLine:
+ if (indexIncreases) {
+ m_currentLangNum++;
+ currentLangLine = MouseSimulator::LanguageLines::FourthLine;
+ } else {
+ m_currentLangNum--;
+ currentLangLine = MouseSimulator::LanguageLines::SecondLine;
+ }
+ break;
+
+ case MouseSimulator::LanguageLines::FourthLine:
+ if (indexIncreases) {
+ m_currentLangNum++;
+ if (m_currentLangNum == KLanguage_List.size()-1) {
+ currentLangLine = MouseSimulator::LanguageLines::FifthLine;
+ }
+ } else {
+ m_currentLangNum--;
+ currentLangLine = MouseSimulator::LanguageLines::ThirdLine;
+ }
+ break;
+
+ case MouseSimulator::LanguageLines::FifthLine:
+ indexIncreases = false;
+ m_currentLangNum--;
+ currentLangLine = MouseSimulator::LanguageLines::FourthLine;
+ break;
+ }
+ }
+
+ m_otherProcHandler->closeProcess();
+ m_timeElapsed = m_testTimer.elapsed();
+
+ if (count == m_numberOfTests && langLayout != 0) {
+ m_passed = true;
+ } else {
+ m_testResult =
+ QString("repeats were expected: %1\nrepeats were verified: %2")
+ .arg(m_numberOfTests).arg(count);
+ }
+
+ emit endTest();
+}
+
+quint8 TestLanguageChange::verifyLanguage(const quint16 num, const bool langLineInListIsKnown)
+{
+ quint8 result = 0;
+ std::map<QString, QVariant> langMap;
+
+ if (FileHelper::getJsonFromFile(QDir::homePath() + KFile_Path_Name, langMap)) {
+ auto lang = langMap["language"].toString();
+
+ if (langLineInListIsKnown) {
+ qCDebug(lcTestLanguageChange) << "language from json:" << lang;
+ QString langFromList = KLanguage_List.at(num).first;
+ qCDebug(lcTestLanguageChange) << "language from list:" << langFromList;
+ if (lang == langFromList) {
+ result = KLanguage_List.at(num).second;
+ }
+ } else {
+ for (auto pair : KLanguage_List) {
+ if (lang == pair.first) {
+ result = pair.second;
+ qCDebug(lcTestLanguageChange) << "Starting language set:" << lang << "with language index:" << m_currentLangNum;
+ break;
+ }
+ m_currentLangNum++;
+ }
+ }
+ }
+ return result;
+}
+
+void TestLanguageChange::deleteTestFile()
+{
+ if (FileHelper::fileExists(QDir::homePath() + KFile_Path_Name)) {
+ std::remove(QString(QDir::homePath() + KFile_Path_Name).toLatin1());
+ }
+}
diff --git a/tests/manual/x11vkbtest/testlanguagechange.h b/tests/manual/x11vkbtest/testlanguagechange.h
new file mode 100644
index 00000000..f49c9379
--- /dev/null
+++ b/tests/manual/x11vkbtest/testlanguagechange.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESTLANGUAGECHANGE_H
+#define TESTLANGUAGECHANGE_H
+
+#include <QObject>
+#include "testbase.h"
+
+class WindowHelper;
+class MouseSimulator;
+class ProcessHandler;
+
+class TestLanguageChange : public TestBase
+{
+ Q_OBJECT
+public:
+ explicit TestLanguageChange(QObject *parent, WindowHelper &windowHelper, quint32 numberOfTests, qint64 x11vkbProcId = 0);
+ ~TestLanguageChange() {}
+
+public:
+ void setProcID(const qint64 procID) {m_x11vkbProcId = procID;}
+
+public slots:
+ void startTest() override;
+
+private slots:
+ void doTest();
+
+private:
+ quint8 verifyLanguage(const quint16 num, const bool langLineInListIsKnown = true);
+ void deleteTestFile();
+
+private:
+ WindowHelper &m_windowHelper;
+ ProcessHandler *m_otherProcHandler;
+ quint8 m_currentLangNum;
+};
+
+#endif // TESTLANGUAGECHANGE_H
diff --git a/tests/manual/x11vkbtest/testreporter.cpp b/tests/manual/x11vkbtest/testreporter.cpp
new file mode 100644
index 00000000..11e24524
--- /dev/null
+++ b/tests/manual/x11vkbtest/testreporter.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QFile>
+#include <QTextStream>
+#include <QVectorIterator>
+#include <QTextStream>
+#include "testreporter.h"
+#include "testbase.h"
+#include "colors.h"
+#include "startclose.h"
+
+namespace {
+const QString KReport_CSV_File = "result.csv";
+const QString KCSV_Column_Separator = ";";
+}
+
+TestReporter::TestReporter(QObject *parent) : QObject(parent)
+{
+}
+
+void TestReporter::startMemoryReport()
+{
+ QFile file(KReport_CSV_File);
+ if (file.open(QIODevice::WriteOnly)) {
+ QTextStream stream(&file);
+ stream << "Time" << KCSV_Column_Separator;
+ stream << "Process Memory size" << KCSV_Column_Separator << endl;
+ file.close();
+ }
+}
+
+void TestReporter::printTestResultsToCSV(const QVector<TestBase *> &tests) const
+{
+ QFile file(KReport_CSV_File);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Append)) {
+ QTextStream stream(&file);
+
+ stream << endl;
+ qint64 timeElapsed = 0;
+ quint8 passed = 0;
+ quint8 failed = 0;
+ bool currentTestIsStartClose = true;
+
+ for (auto test : tests) {
+ if (nullptr == qobject_cast<StartClose*>(test)) {
+ currentTestIsStartClose = false;
+ if (test->passed()) {
+ stream << "PASS" << KCSV_Column_Separator;
+ passed++;
+ } else {
+ stream << "FAIL" << KCSV_Column_Separator;
+ failed++;
+ }
+ }
+ stream << test->testName() << KCSV_Column_Separator
+ << test->timeElapsed() << "s" << endl;
+
+ QString extraInfo = test->reportResult();
+ if (!extraInfo.isEmpty()) {
+ extraInfo.replace(QString(": "), QString(KCSV_Column_Separator));
+ stream << extraInfo << endl;
+ }
+ timeElapsed = timeElapsed + test->timeElapsed();
+
+ if (currentTestIsStartClose) {
+ stream << endl;
+ }
+ }
+
+ stream << endl;
+ stream << "Totals" << KCSV_Column_Separator << passed << " passed "
+ << KCSV_Column_Separator << failed << " failed"
+ << KCSV_Column_Separator << timeElapsed << "s";
+ stream << endl;
+ file.close();
+ }
+}
+
+void TestReporter::printMemoryResultToCSV(QString minPeakMemoryReport) const
+{
+ QFile file(KReport_CSV_File);
+
+ if (file.open(QIODevice::WriteOnly | QIODevice::Append)) {
+ QTextStream stream(&file);
+ minPeakMemoryReport.replace(QString(": "), QString(KCSV_Column_Separator));
+ stream << minPeakMemoryReport << endl;
+ file.close();
+ }
+}
+
+void TestReporter::printTestResultToConsole(const QVector<TestBase *> &tests) const
+{
+ QTextStream stream(stdout);
+
+ qint64 timeElapsed = 0;
+ quint8 passed = 0;
+ quint8 failed = 0;
+
+ for (auto test : tests) {
+ if (nullptr == qobject_cast<StartClose*>(test)) {
+ if (test->passed()) {
+ stream << FBold(FGreen("PASS: "));
+ passed++;
+ } else {
+ stream << FBold(FRed("FAIL:"));
+ failed++;
+ }
+ }
+ stream << test->testName() << " " << test->timeElapsed() << "s" << endl;
+ QString extraInfo = test->reportResult();
+ if (!extraInfo.isEmpty()) {
+ stream << extraInfo << endl;
+ }
+
+ timeElapsed = timeElapsed + test->timeElapsed();
+ }
+
+ stream << "Totals: " << passed << " passed, " << failed << " failed. " << timeElapsed << "s";
+ stream << endl;
+}
+
+void TestReporter::currentMemUsage(const quint64 timeElapsed, const ulong memSize) const
+{
+ QFile file(KReport_CSV_File);
+
+ if (file.open(QIODevice::WriteOnly | QIODevice::Append)) {
+ QTextStream stream(&file);
+ stream << timeElapsed << "s" << KCSV_Column_Separator;
+ stream << memSize << " KB" << KCSV_Column_Separator << endl;
+ file.close();
+ }
+}
diff --git a/tests/manual/x11vkbtest/testreporter.h b/tests/manual/x11vkbtest/testreporter.h
new file mode 100644
index 00000000..2a6d2c5f
--- /dev/null
+++ b/tests/manual/x11vkbtest/testreporter.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CSVPRINTER_H
+#define CSVPRINTER_H
+
+#include <QObject>
+
+class TestBase;
+
+class TestReporter : public QObject
+{
+ Q_OBJECT
+public:
+ explicit TestReporter(QObject *parent = nullptr);
+
+public:
+ void startMemoryReport();
+ void printTestResultsToCSV(const QVector<TestBase*> &tests) const;
+ void printTestResultToConsole(const QVector<TestBase *> &tests) const;
+
+public slots:
+ void printMemoryResultToCSV(const QString minPeakMemoryReport) const;
+ void currentMemUsage(const quint64 timeElapsed, const ulong memSize) const;
+};
+
+#endif // CSVPRINTER_H
diff --git a/tests/manual/x11vkbtest/testthread.cpp b/tests/manual/x11vkbtest/testthread.cpp
new file mode 100644
index 00000000..8bf4556c
--- /dev/null
+++ b/tests/manual/x11vkbtest/testthread.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QEventLoop>
+#include <QFile>
+#include <QElapsedTimer>
+#include <QLoggingCategory>
+
+#include "testreporter.h"
+#include "processhandler.h"
+#include "startclose.h"
+#include "testenglishletters.h"
+#include "testlanguagechange.h"
+#include "testthread.h"
+#include "windowhelper.h"
+
+namespace {
+const quint32 KTime_Wait_To_Start_Test = 1000000;
+}
+
+Q_LOGGING_CATEGORY(lcTestThread, "qt.virtualkeyboard.tests.manual.x11vkbtest.testthread")
+
+TestThread::TestThread(const QString &x11vkbPath, quint32 startCloseTest, quint32 keyOperationTest, quint32 langChangeTest, QObject *parent) :
+ QThread(parent),
+ m_x11vkbPath(x11vkbPath),
+ m_numberOfStartClose(startCloseTest),
+ m_numberOfKeyOperation(keyOperationTest),
+ m_numberOfLangChange(langChangeTest)
+{
+}
+
+void TestThread::run()
+{
+ QElapsedTimer testTimer;
+ testTimer.start();
+
+ QVector<TestBase*> tests;
+
+ TestReporter reporter;
+ WindowHelper windowHelper;
+ auto x11vkbProcHandler = new ProcessHandler(&windowHelper, m_x11vkbPath);
+
+ if (m_numberOfStartClose > 0 || (m_numberOfKeyOperation == 0 && m_numberOfLangChange == 0)) {
+ auto startClose = new StartClose(*x11vkbProcHandler->getPRocess(), m_numberOfStartClose, &windowHelper);
+ tests.append(startClose);
+ }
+
+ if (m_numberOfKeyOperation > 0 || (m_numberOfStartClose == 0 && m_numberOfLangChange == 0)) {
+ auto testEngLetters = new TestEnglishLetters(&windowHelper, windowHelper, m_numberOfKeyOperation);
+ tests.append(testEngLetters);
+ }
+
+ if (m_numberOfLangChange > 0 || (m_numberOfStartClose == 0 && m_numberOfKeyOperation == 0)) {
+ auto testLang = new TestLanguageChange(&windowHelper, windowHelper, m_numberOfLangChange);
+ tests.append(testLang);
+ }
+
+ bool startVKB = true;
+ if (tests.size() == 1 && nullptr != qobject_cast<StartClose*>(tests.first())) {
+ startVKB = false;
+ }
+ /* main loop to connect test each after another */
+ for (int i = 0 ; i < tests.size() - 1 ; ++i) {
+ if (nullptr != qobject_cast<StartClose*>(tests.at(i))) {
+ QObject::connect(tests.at(i), &StartClose::endTest, [&]() {
+
+ auto x11vkbProcId = x11vkbProcHandler->getProcId();
+
+ emit processID(x11vkbProcId);
+
+ for (int i = 1 ; i < tests.size() ; ++i) {
+ tests.at(i)->setProcID(x11vkbProcId);
+ }
+ if (tests.size() > 1) {
+ emit startMemoryMonitor();
+ usleep(KTime_Wait_To_Start_Test);
+ tests.at(1)->startTest();
+ }
+ });
+ startVKB = false;
+ } else {
+ QObject::connect(tests.at(i), &TestBase::endTest, tests.at(i+1), &TestBase::startTest);
+ }
+ }
+
+ if (startVKB) {
+ emit startMemoryMonitor();
+ x11vkbProcHandler->startProc();
+ qCDebug(lcTestThread) << "Explicitly start process";
+ auto x11vkbProcId = x11vkbProcHandler->getProcId();
+
+ emit processID(x11vkbProcId);
+
+ for (auto test : tests) {
+ test->setProcID(x11vkbProcId);
+ }
+ usleep(KTime_Wait_To_Start_Test);
+ }
+
+ QObject::connect(tests.last(), &TestBase::endTest, this, &QThread::quit);
+
+ tests.first()->startTest();
+ exec();
+
+ reporter.printTestResultsToCSV(tests);
+ reporter.printTestResultToConsole(tests);
+
+ x11vkbProcHandler->closeProcess();
+}
diff --git a/tests/manual/x11vkbtest/testthread.h b/tests/manual/x11vkbtest/testthread.h
new file mode 100644
index 00000000..f10e1497
--- /dev/null
+++ b/tests/manual/x11vkbtest/testthread.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESTTHREAD_H
+#define TESTTHREAD_H
+
+#include <QThread>
+#include "testbase.h"
+
+class TestBase;
+
+class TestThread : public QThread
+{
+ Q_OBJECT
+public:
+ explicit TestThread(const QString &x11vkbPath, quint32 startCloseTest, quint32 keyOperationTest, quint32 langChangeTest, QObject *parent = nullptr);
+
+public:
+ void run() override;
+
+signals:
+ void resultReady(const QString &s);
+ void processID(const qint64 procID);
+ void startMemoryMonitor();
+
+private:
+ const QString &m_x11vkbPath;
+ quint32 m_numberOfStartClose;
+ quint32 m_numberOfKeyOperation;
+ quint32 m_numberOfLangChange;
+};
+
+#endif // TESTTHREAD_H
diff --git a/tests/manual/x11vkbtest/windowhelper.cpp b/tests/manual/x11vkbtest/windowhelper.cpp
new file mode 100644
index 00000000..9223774b
--- /dev/null
+++ b/tests/manual/x11vkbtest/windowhelper.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QTextStream>
+#include <cstdlib>
+
+extern "C" {
+#include <xdo.h>
+#include <X11/X.h>
+}
+
+#include <cstdio>
+#include <cstdlib>
+
+#include "windowhelper.h"
+
+WindowHelper::WindowHelper(QObject *parent) :
+ QObject(parent),
+ m_xdo(xdo_new(nullptr))
+{
+}
+
+WindowHelper::~WindowHelper()
+{
+ xdo_free(m_xdo);
+}
+
+Window WindowHelper::findWindowByPid(const qint64 appPid) const
+{
+ xdo_search_t search;
+ memset(&search, 0, sizeof(xdo_search_t));
+
+ search.require = xdo_search::SEARCH_ANY;
+ search.searchmask = SEARCH_PID;
+ search.pid = static_cast<int>(appPid);
+ search.max_depth = -1;
+
+ Window *list;
+ quint32 nwindows = 0;
+
+ xdo_search_windows(m_xdo, &search, &list, &nwindows);
+
+ return nwindows > 0 ? list[nwindows-1] : 0;
+}
+
+QPair<quint16, quint16> WindowHelper::getWindowDimension(const Window winId) const
+{
+ Display *display = XOpenDisplay(nullptr);
+ XWindowAttributes winAttributes;
+ XGetWindowAttributes(display, winId, &winAttributes);
+
+ XCloseDisplay(display);
+
+ return {static_cast<quint16>(winAttributes.width), static_cast<quint16>(winAttributes.height)};
+}
diff --git a/tests/manual/x11vkbtest/windowhelper.h b/tests/manual/x11vkbtest/windowhelper.h
new file mode 100644
index 00000000..e9871737
--- /dev/null
+++ b/tests/manual/x11vkbtest/windowhelper.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WINDOWHELPER_H
+#define WINDOWHELPER_H
+
+#include <QObject>
+
+extern "C" {
+#include <xdo.h>
+}
+
+class WindowHelper : public QObject
+{
+ Q_OBJECT
+public:
+ explicit WindowHelper(QObject *parent = nullptr);
+ ~WindowHelper();
+
+public:
+ Window findWindowByPid(const qint64 appPid) const;
+ QPair<quint16, quint16> getWindowDimension(const Window winId) const;
+
+private:
+ /** Libxdo context. */
+ xdo_t *m_xdo;
+};
+
+#endif // WINDOWHELPER_H
diff --git a/tests/manual/x11vkbtest/x11vkbtest.pro b/tests/manual/x11vkbtest/x11vkbtest.pro
new file mode 100644
index 00000000..74623f89
--- /dev/null
+++ b/tests/manual/x11vkbtest/x11vkbtest.pro
@@ -0,0 +1,41 @@
+TARGET = x11vkbtest
+
+QT += charts
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+SOURCES += \
+ filehelper.cpp \
+ main.cpp \
+ memorymonitor.cpp \
+ mousesimulator.cpp \
+ processhandler.cpp \
+ startclose.cpp \
+ testbase.cpp \
+ testenglishletters.cpp \
+ testlanguagechange.cpp \
+ testreporter.cpp \
+ testthread.cpp \
+ windowhelper.cpp
+
+HEADERS += \
+ colors.h \
+ filehelper.h \
+ memorymonitor.h \
+ mousesimulator.h \
+ processhandler.h \
+ startclose.h \
+ testbase.h \
+ testenglishletters.h \
+ testlanguagechange.h \
+ testreporter.h \
+ testthread.h \
+ windowhelper.h
+
+LIBS += -lXtst -lX11 -lxdo