aboutsummaryrefslogtreecommitdiffstats
path: root/tests/manual/x11vkbtest
diff options
context:
space:
mode:
authorMikko Seppänen <mikko.seppanen123@gmail.com>2019-06-19 15:56:13 +0300
committerJani Heikkinen <jani.heikkinen@qt.io>2019-10-08 10:53:15 +0000
commitae362d1e7ea48a2620a121f2848a9f12fa82d498 (patch)
treea0045479d86e9962ada7c7ea9de32ad1a98d5d9d /tests/manual/x11vkbtest
parent932ae053ab9ea8aed974e8dde1bf7ef8524826a3 (diff)
Qt virtual keyboard wrapper for X11v5.14.0-beta2
This application is a Qt virtual keyboard wrapper that uses Qt virtual keyboard for any X11 input. Application uses At-Spi2 library for listening focus-in events on text widgets and pops up the Qt virtual keyboard when an accepted focus-in event is received. There's also support for listening focus-in events from Chromium browser. For mapping and sending the key events to focused text widget the application uses libXtst, libX11 and libxdo which are also external dependencies to the application among At-Spi2 library. Change-Id: Ifa54969ab4f61e1d48f11ca11058c836f2a403b8 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> (cherry picked from commit fb9e76c9ebcc9ca98ff04e7310a12b4511fa5539)
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