aboutsummaryrefslogtreecommitdiffstats
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
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)
-rw-r--r--tests/manual/manual.pro5
-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
-rw-r--r--tests/manual/x11vkbwrapper/README.md61
-rw-r--r--tests/manual/x11vkbwrapper/chromeextension/background.js76
-rw-r--r--tests/manual/x11vkbwrapper/chromeextension/content.js91
-rw-r--r--tests/manual/x11vkbwrapper/chromeextension/icons/Qt_logo.pngbin0 -> 35615 bytes
-rw-r--r--tests/manual/x11vkbwrapper/chromeextension/manifest.json36
-rw-r--r--tests/manual/x11vkbwrapper/common_defs.h36
-rw-r--r--tests/manual/x11vkbwrapper/graphics/Qt_logo.pngbin0 -> 35615 bytes
-rw-r--r--tests/manual/x11vkbwrapper/handleatspievents.cpp217
-rw-r--r--tests/manual/x11vkbwrapper/handleatspievents.h62
-rw-r--r--tests/manual/x11vkbwrapper/handledbusforchrome.cpp49
-rw-r--r--tests/manual/x11vkbwrapper/handledbusforchrome.h63
-rw-r--r--tests/manual/x11vkbwrapper/handlekeyevents.cpp232
-rw-r--r--tests/manual/x11vkbwrapper/handlekeyevents.h68
-rw-r--r--tests/manual/x11vkbwrapper/handlelanguagechange.cpp78
-rw-r--r--tests/manual/x11vkbwrapper/handlelanguagechange.h47
-rw-r--r--tests/manual/x11vkbwrapper/keyboard.qml77
-rw-r--r--tests/manual/x11vkbwrapper/keysymmapsforfakeinput.h299
-rw-r--r--tests/manual/x11vkbwrapper/main.cpp128
-rw-r--r--tests/manual/x11vkbwrapper/main.qml60
-rw-r--r--tests/manual/x11vkbwrapper/qml.qrc7
-rw-r--r--tests/manual/x11vkbwrapper/vkbhidetimer.cpp63
-rw-r--r--tests/manual/x11vkbwrapper/vkbhidetimer.h63
-rw-r--r--tests/manual/x11vkbwrapper/vkbnativehost/common_defs.h35
-rwxr-xr-xtests/manual/x11vkbwrapper/vkbnativehost/install_host.sh82
-rw-r--r--tests/manual/x11vkbwrapper/vkbnativehost/main.cpp47
-rw-r--r--tests/manual/x11vkbwrapper/vkbnativehost/sendertodbus.cpp90
-rw-r--r--tests/manual/x11vkbwrapper/vkbnativehost/sendertodbus.h64
-rw-r--r--tests/manual/x11vkbwrapper/vkbnativehost/vkbnativehost.pro26
-rw-r--r--tests/manual/x11vkbwrapper/vkbnativehost/x11vkb.host.json9
-rw-r--r--tests/manual/x11vkbwrapper/x11vkbwrapper.pro54
-rw-r--r--tests/manual/x11vkbwrapper/xcbkeyboard.h604
57 files changed, 5484 insertions, 0 deletions
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
new file mode 100644
index 00000000..671e7a13
--- /dev/null
+++ b/tests/manual/manual.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+SUBDIRS += \
+ x11vkbwrapper \
+ x11vkbtest
+
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
diff --git a/tests/manual/x11vkbwrapper/README.md b/tests/manual/x11vkbwrapper/README.md
new file mode 100644
index 00000000..134dd4af
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/README.md
@@ -0,0 +1,61 @@
+# Qt virtual keyboard wrapper for X11
+
+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.
+
+## Libraries to be installed
+libatspi2.0-dev libxdo-dev libxtst-dev
+
+## Running the x11vkbwrapper
+1. Build the x11vkbwrapper project.
+2. For x11vkbwrapper application to be able to send key events to X11 clients and to enable the SHIFT - key the run environment for x11vkbwrapper application has to have environment variable QT_VIRTUALKEYBOARD_FORCE_EVENTS_WITHOUT_FOCUS set.
+ It can be empty but it has to be set. Setting the environment variable enables usage of the virtual keyboard input method without a focused Qt specific input object.
+3. If Firefox is to be used the environment variable GNOME_ACCESSIBILITY has to be set to 1 to enable the At-Spi support.
+4. Run the x11vkbwrapper.
+
+## Enable Chrome/Chromium support
+1. Build the vkbnativehost project.
+2. From vkbnativehost folder run shell script install_host.sh with following parameters: "chromium" "/full/path/to/vkbnativehost_executable". Exclude the filename from the path.
+ 1. For chrome browser replace the "chromium" parameter with "chrome".
+ 2. The script updates the path to vkbnativehost executable in x11vkb.host.json file and copies that .json file into the current user local space $HOME/.config/chromium/NativeMessagingHosts.
+ 3. If sudo is used .json file will be copied in chromium global space /etc/chromium-browser/native-messaging-hosts.
+3. In Chromium/Chrome browser go to url chrome://extensions/.
+4. Enable Developer Mode by clicking the toggle switch next to Developer mode.
+5. Click the "Load unpacked" button and provide there the chromeextension folder.
+6. x11vkbwrapper must be running before the browser is started to have the show/hide keyboard support enabled.
+
+## Setting up and running the x11vkbtest test application
+### Background
+Test application (x11vkbtest) will start the x11vkbwrapper and uses Linux proc filesystem for obtaining memory consumption information and libXtst, libX11 and libxdo libraries for generating and sending key events.
+There are three different tests that can be run:
+1. Testing the start/close cycle of the x11vkbwrapper application is run in 50ms intervals and the current free system memory is recorded at the beginning and at the end of the test. By default amount of 50 start/close cycles will be run.
+2. Key event test opens up gedit text editor and sends key events to the x11vkbwrapper app in 50ms interval writing by default a 100 character string or a string as long as user has defined to gedit and verifies the results by comparing the written text to the predefined one.
+3. Language change test sends key events to the x11vkbwrapper app in 120ms interval making the language change to take place. Result is verified against information on input context locale's native language name read from a .json file produced by the app under test (x11vkbwrapper). By default amount of 10 language change events will be performed.
+
+Test results are produced in a form of csv file and an png image of the memory consumption chart in a folder where this application is run. Test report includes the duration of each test, memory consumption information on the system and the process being tested and the overall duration of all tests that has been run.
+
+### Steps to build and run x11vkbtest
+1. Build the x11vkbtest project.
+2. Uncomment 'DEFINES += QT_TESTING_RUN' from x11vkbwrapper.pro and build/re-build it preferably in RELEASE mode.
+ 1. The above given DEFINES+=QT_TESTING_RUN enables x11vkbwrapper app to write the current selected language in qtvirtualkeyboard into a .json file in /home/<username</x11vkbwrapper_language/currentLang.json which will be used by x11vkbtest to obtain the current selected language when testing the language change events.
+3. To be able to start running the tests command line argument --exec <absolute_path_to_x11vkbwrapper_executable> needs to be given when starting the x11vkbtest app and environment variable QT_VIRTUALKEYBOARD_FORCE_EVENTS_WITHOUT_FOCUS needs to be set.
+4. The three tests that can be run as a series or separately:
+ 1. Start & close the x11vkbwrapper application
+ 1. command line argument --sc <number_of_times>
+ 2. Key events
+ 1. command line argument --ko <number_of_keyevents>
+ 3. Language change events
+ 1. command line argument --lc <number_of_language_changes>
+5. If no command line arguments are specified all of the tests are run in the order specified above using default values.
+6. If parameters --sc, --ko and/or --lc are used the corresponding value(s) has/have to be given explicitly.
+7. Example command line arguments: --exec <absolute_path_to_x11vkbwrapper> --sc 100 --lc 100
+
+The --sc test doesn't produce any visible results in the chart and it will run approximately few seconds when no parameter --sc with a value specifying the start/close cycles has been given. If --sc <number_of_times> has been given then bigger the number the longer the time is that nothing is visually happening during the --sc test, only a static chart is visible. During --ko and --lc tests live memory consumption is drawn to the chart.
+No interaction, mouse or keyboard etc., should be performed during the test run. It will cause libx11 pointer coordinate getting- and libxtst button event sending functions to go haywire
+and thus x11vkbtest will fail to click on correct points on the x11vkbwrapper keyboard.
diff --git a/tests/manual/x11vkbwrapper/chromeextension/background.js b/tests/manual/x11vkbwrapper/chromeextension/background.js
new file mode 100644
index 00000000..67460404
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/chromeextension/background.js
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+const hostName = "x11vkb.host";
+var port = null;
+var currentTabId = 0;
+var context_id = -1;
+
+chrome.input.ime.onFocus.addListener(function(context) {
+ context_id = context.contextID;
+});
+
+function sendNativeMessage(message, sender)
+{
+ if (port) {
+ port.postMessage(message);
+ }
+}
+
+function onDisconnected()
+{
+ port = null;
+}
+
+function connect()
+{
+ port = chrome.runtime.connectNative(hostName);
+ port.onDisconnect.addListener(onDisconnected);
+}
+
+chrome.runtime.onStartup.addListener(function() {
+ connect();
+})
+
+chrome.runtime.onMessage.addListener(sendNativeMessage);
+
+chrome.tabs.onCreated.addListener(function (props) {
+// console.log("onCreated, props.url", props.url)
+ });
+
+chrome.tabs.onActiveChanged.addListener(function (props, changeInfo, tab) {
+ chrome.tabs.sendMessage(props, "onActive");
+ });
+
+chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
+ if (changeInfo.status == 'complete' && tab.active)
+ {
+ chrome.tabs.sendMessage(tabId, "onActiveChanged");
+ }
+ });
diff --git a/tests/manual/x11vkbwrapper/chromeextension/content.js b/tests/manual/x11vkbwrapper/chromeextension/content.js
new file mode 100644
index 00000000..dcc8c840
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/chromeextension/content.js
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+var lastActiveElement = null;
+var inputs = ['input', 'textarea'];
+var types = ['text', 'password', 'email', 'number', 'search', 'url', 'date', 'tel', 'time'];
+var sentValue = 0;
+
+function sendValue(value)
+{
+ sentValue = value;
+ chrome.runtime.sendMessage(sentValue);
+}
+
+
+if (inputs.indexOf(document.activeElement.nodeName.toLowerCase()) !== -1) {
+ sendValue(1);
+}
+
+function detectBlur()
+{
+ lastActiveElement = document.activeElement;
+ if (sentValue === 1)
+ {
+ sendValue(0);
+ }
+}
+
+function isSameActiveElement()
+{
+ var currentActiveElement = document.activeElement;
+ if (lastActiveElement !== currentActiveElement) {
+ lastActiveElement = currentActiveElement;
+ return false;
+ }
+ return true;
+}
+
+function detectFocus()
+{
+ if (!isSameActiveElement() &&
+ (inputs.indexOf(document.activeElement.nodeName.toLowerCase()) !== -1) &&
+ (types.indexOf(document.activeElement.type.toLowerCase()) !== -1))
+ {
+ sendValue(1);
+ }
+}
+
+window.onblur = function(e) {
+ lastActiveElement = null;
+}
+
+
+function attachEvents()
+{
+ window.addEventListener ? window.addEventListener('focus', detectFocus, true) : window.attachEvent('onfocusout', detectFocus);
+ window.addEventListener ? window.addEventListener('blur', detectBlur, true) : window.attachEvent('onblur', detectBlur);
+}
+
+chrome.runtime.onMessage.addListener(function(message) {
+ lastActiveElement = null;
+ detectFocus();
+});
+
+attachEvents();
diff --git a/tests/manual/x11vkbwrapper/chromeextension/icons/Qt_logo.png b/tests/manual/x11vkbwrapper/chromeextension/icons/Qt_logo.png
new file mode 100644
index 00000000..901ec2f9
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/chromeextension/icons/Qt_logo.png
Binary files differ
diff --git a/tests/manual/x11vkbwrapper/chromeextension/manifest.json b/tests/manual/x11vkbwrapper/chromeextension/manifest.json
new file mode 100644
index 00000000..04608b78
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/chromeextension/manifest.json
@@ -0,0 +1,36 @@
+{
+ "manifest_version": 2,
+ "key": "bbngehjagobenpfgjcpmfigfanlomdkk",
+ "name": "Qt Virtual Keyboard",
+ "version": "1.0",
+ "browser_action": {
+ "default_icon": {
+ "32": "icons/Qt_logo.png"
+ },
+ "default_title": "Qt Keyboard"
+ },
+ "permissions": [
+ "*://*/*",
+ "tabs",
+ "storage",
+ "nativeMessaging",
+ "notifications",
+ "webNavigation",
+ "input",
+ "idle",
+ "bookmarks"
+ ],
+ "background": {
+ "scripts": [ "background.js" ],
+ "persistent": false
+ },
+ "icons": {
+ "32": "icons/Qt_logo.png"
+ },
+ "content_scripts": [
+ {
+ "matches" : ["*://*/*"],
+ "js": ["content.js"]
+ }
+ ]
+}
diff --git a/tests/manual/x11vkbwrapper/common_defs.h b/tests/manual/x11vkbwrapper/common_defs.h
new file mode 100644
index 00000000..41eb288f
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/common_defs.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** 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 COMMONDEFS_H
+#define COMMONDEFS_H
+
+#define SERVICE_NAME "x11vkb.chromium.dbus.service"
+
+#endif // COMMONDEFS_H
+
diff --git a/tests/manual/x11vkbwrapper/graphics/Qt_logo.png b/tests/manual/x11vkbwrapper/graphics/Qt_logo.png
new file mode 100644
index 00000000..901ec2f9
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/graphics/Qt_logo.png
Binary files differ
diff --git a/tests/manual/x11vkbwrapper/handleatspievents.cpp b/tests/manual/x11vkbwrapper/handleatspievents.cpp
new file mode 100644
index 00000000..ed330e0c
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/handleatspievents.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** 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 <QLoggingCategory>
+#include <QTime>
+#include <QGuiApplication>
+#include <QMutableVectorIterator>
+
+#include "handleatspievents.h"
+#include "vkbhidetimer.h"
+#include "atspi/atspi.h"
+
+namespace {
+const QString KAtspiBusLauncher = "at-spi-bus-launcher";
+const QString KAtspiRegistryd = "at-spi2-registryd";
+const int KProsessIsRunning = 0;
+}
+
+Q_LOGGING_CATEGORY(lcHandleAtspiEvents, "qt.virtualkeyboard.tests.manual.x11vkbwrapper.handleatspievents")
+
+/**
+ * @brief focusEventFromInput Called when a widget is focused.
+ * @param event
+ * @param user_data
+ */
+ void focusEventFromInput(AtspiEvent *event, void *user_data)
+{
+ qCDebug(lcHandleAtspiEvents) << Q_FUNC_INFO;
+ auto *handleATSPIEvents = static_cast<HandleATSPIEvents *>(user_data);
+ handleATSPIEvents->gotFocusEventFromInput(event);
+}
+
+/**
+ * @brief HandleATSPIEvents::HandleATSPIEvents
+ * @param parent
+ */
+HandleATSPIEvents::HandleATSPIEvents(QObject *parent)
+ : QObject(parent),
+ m_keyboardVisible(false),
+ m_focuses(0)
+{
+
+}
+
+/**
+ * @brief HandleATSPIEvents::~HandleATSPIEvents
+ */
+HandleATSPIEvents::~HandleATSPIEvents()
+{
+ qCDebug(lcHandleAtspiEvents) << Q_FUNC_INFO;
+
+ m_focuses.clear();
+
+ if (!atspi_event_listener_deregister_from_callback(focusEventFromInput, static_cast<void*>(this), "object:state-changed:focused", nullptr)) {
+ qWarning() << "Error occurred: Problem deregistering focus listener";
+ }
+}
+
+/**
+ * @brief HandleATSPIEvents::init
+ * @return false if at-spi is not running or callback regitering fail
+ */
+
+bool HandleATSPIEvents::init()
+{
+ qCDebug(lcHandleAtspiEvents) << Q_FUNC_INFO;
+ /** Check that At-spi is running */
+ if (KProsessIsRunning != system(QString("pidof -x %1 > /dev/null").arg(KAtspiBusLauncher).toLatin1().data()) ||
+ KProsessIsRunning != system(QString("pidof -x %1 > /dev/null").arg(KAtspiRegistryd).toLatin1().data())) {
+ qWarning() << "One or both of the At-Spi related processes are not running.";
+ return false;
+ }
+
+ GError *error = nullptr;
+ /** Registered the spi events to monitor focus and show on editable widgets. */
+ if (!atspi_event_listener_register_from_callback(focusEventFromInput,
+ static_cast<void*>(this),
+ nullptr,
+ "object:state-changed:focused",
+ &error)){
+ qWarning() << Q_FUNC_INFO << "Error occurred: ATSPI listener register failed. Error message:" << error->message;
+ return false;
+ }
+
+ QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::visibleChanged, [this] {
+ this->setKeyboardVisible(QGuiApplication::inputMethod()->isVisible());
+ });
+
+ return true;
+}
+
+/**
+ * @brief handleATSPIEvents::setKeyboardVisible
+ * @param visible
+ */
+void HandleATSPIEvents::setKeyboardVisible(const bool visible)
+{
+ if (m_keyboardVisible != visible) {
+ m_keyboardVisible = visible;
+ qCDebug(lcHandleAtspiEvents) << "SET VKB visible " << visible;
+ if (m_keyboardVisible && !QGuiApplication::inputMethod()->isVisible()) {
+ QGuiApplication::inputMethod()->show();
+ } else {
+ QGuiApplication::inputMethod()->hide();
+ }
+ }
+}
+
+/**
+ * @brief handleATSPIEvents::storeFocusElement
+ * @param role
+ * @param focus
+ */
+void HandleATSPIEvents::storeFocusElement(const qint8 role)
+{
+ m_focuses.append(role);
+ qCDebug(lcHandleAtspiEvents) << "*****INSERTED FOCUS ELEMENT*****" << role << "TOTAL:" << m_focuses.length();
+}
+
+/**
+ * @brief handleATSPIEvents::isThereFocus
+ * AT-SPI focus in/out events are received in random order and for some
+ * objects AT-SPI doesn't send any focus OUT event at all.
+ * This function keeps track if there's an accepted type of object in focus and
+ * knows to release/ignore the objects that do not receive focus OUT event.
+ * @param role
+ */
+bool HandleATSPIEvents::isThereFocus(const qint8 role)
+{
+ qCDebug(lcHandleAtspiEvents) << " FOCUS ELEMENT to EXAMINE: " << role;
+ qint8 roleValue = ATSPI_ROLE_INVALID;
+ for (auto iter = m_focuses.begin() ; iter != m_focuses.end() ; iter++) {
+ roleValue = *iter;
+ if (roleValue == role ||
+ roleValue == ATSPI_ROLE_DOCUMENT_WEB ||
+ roleValue == ATSPI_ROLE_ENTRY ||
+ roleValue == ATSPI_ROLE_LINK) {
+ qCDebug(lcHandleAtspiEvents) << "*****REMOVING FOCUS ELEMENT*****: " << *iter;
+ m_focuses.erase(iter--);
+ }
+ }
+ m_focuses.squeeze();
+ return !m_focuses.isEmpty();
+}
+
+/**
+ * @brief handleATSPIEvents::gotFocusEventFromInput
+ * @param event
+ */
+void HandleATSPIEvents::gotFocusEventFromInput(const AtspiEvent *event)
+{
+ qCDebug(lcHandleAtspiEvents) << Q_FUNC_INFO << event->type << event->detail1 << event->detail2 << QTime::currentTime().toString();
+
+ GError *error = nullptr;
+ AtspiStateSet *state_set = atspi_accessible_get_state_set(event->source);
+ AtspiRole role = atspi_accessible_get_role(event->source, &error);
+
+ if (error) {
+ qCDebug(lcHandleAtspiEvents) << Q_FUNC_INFO << "Event error message:" << error->message;
+ }
+ qCDebug(lcHandleAtspiEvents) << "ATSPI focus event received. Object role=" << role;
+
+ if ((((role == ATSPI_ROLE_TERMINAL) || (role == ATSPI_ROLE_PANEL) ||
+ (role == ATSPI_ROLE_TABLE_CELL) ||
+ (((role == ATSPI_ROLE_TEXT) ||
+ (role == ATSPI_ROLE_PASSWORD_TEXT) ||
+ (role == ATSPI_ROLE_SECTION) ||
+ (role == ATSPI_ROLE_PARAGRAPH) ||
+ (role = ATSPI_ROLE_ENTRY)) &&
+ state_set &&
+ atspi_state_set_contains(state_set, ATSPI_STATE_EDITABLE))))) {
+
+ if (event->detail1) {
+ qCDebug(lcHandleAtspiEvents) << "ACCEPTED FOCUS IN";
+ VkbHideTimer::getInstance()->startTimer();
+ this->storeFocusElement(role);
+ if (!m_keyboardVisible) {
+ setKeyboardVisible(true);
+ }
+ } else if (m_keyboardVisible && !isThereFocus(role)) {
+ setKeyboardVisible(false);
+ }
+
+ } else {
+ qCDebug(lcHandleAtspiEvents) << " ELSE: SET VKB visible FALSE";
+ setKeyboardVisible(false);
+ m_focuses.clear();
+ m_focuses.squeeze();
+ }
+}
+
diff --git a/tests/manual/x11vkbwrapper/handleatspievents.h b/tests/manual/x11vkbwrapper/handleatspievents.h
new file mode 100644
index 00000000..677015ff
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/handleatspievents.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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 HANDLEATSPIEVENTS_H
+#define HANDLEATSPIEVENTS_H
+
+#include <QObject>
+#include <QVector>
+#include <atspi/atspi.h>
+
+class HandleATSPIEvents : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit HandleATSPIEvents(QObject *parent = nullptr);
+ ~HandleATSPIEvents();
+
+ bool init();
+
+ void gotFocusEventFromInput(const AtspiEvent *event);
+
+
+private:
+ void storeFocusElement(const qint8 role);
+ bool isThereFocus(const qint8 role);
+
+public slots:
+ void setKeyboardVisible(const bool visible);
+
+private:
+ bool m_keyboardVisible;
+ QVector<qint8> m_focuses;
+};
+
+#endif // HANDLEATSPIEVENTS_H
diff --git a/tests/manual/x11vkbwrapper/handledbusforchrome.cpp b/tests/manual/x11vkbwrapper/handledbusforchrome.cpp
new file mode 100644
index 00000000..a53ed80c
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/handledbusforchrome.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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 "handledbusforchrome.h"
+#include "vkbhidetimer.h"
+
+HandleDbusForChrome::HandleDbusForChrome(QObject *obj)
+ : QDBusAbstractAdaptor(obj),
+ m_focusValue(false)
+{ }
+
+// the property
+bool HandleDbusForChrome::focusValue() const
+{
+ return m_focusValue;
+}
+
+void HandleDbusForChrome::setFocusValue(bool newValue)
+{
+ m_focusValue = newValue;
+ emit showKeyboard(m_focusValue);
+ VkbHideTimer::getInstance()->startTimer();
+}
diff --git a/tests/manual/x11vkbwrapper/handledbusforchrome.h b/tests/manual/x11vkbwrapper/handledbusforchrome.h
new file mode 100644
index 00000000..0962b1f0
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/handledbusforchrome.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 HANDLEDBUSFORCHROME_H
+#define HANDLEDBUSFORCHROME_H
+
+#include <QtCore/QObject>
+#include <QtDBus/QDBusAbstractAdaptor>
+#include "common_defs.h"
+
+class HandleDbusForChrome: public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", SERVICE_NAME)
+ Q_PROPERTY(bool focusValue READ focusValue WRITE setFocusValue)
+
+public:
+ HandleDbusForChrome(QObject *obj);
+
+ bool focusValue() const;
+ void setFocusValue(bool newValue);
+
+signals:
+ //!
+ //! \brief showKeyboard
+ //! signal for request by param value to popup or hide keyboard.
+ //! it is sent when setValue is called via dbus
+ //! \param bool focusValue
+ //!
+ void showKeyboard(bool focusValue);
+
+private:
+ bool m_focusValue;
+
+};
+
+#endif // HANDLEDBUSFORCHROME_H
diff --git a/tests/manual/x11vkbwrapper/handlekeyevents.cpp b/tests/manual/x11vkbwrapper/handlekeyevents.cpp
new file mode 100644
index 00000000..0c3c85a4
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/handlekeyevents.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** 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 <QtVirtualKeyboard>
+#include <QApplication>
+#include <QLoggingCategory>
+
+#include "handlekeyevents.h"
+#include "vkbhidetimer.h"
+#include "xcbkeyboard.h"
+#include "keysymmapsforfakeinput.h"
+
+extern "C" {
+#include <xdo.h>
+#include <X11/extensions/XTest.h>
+}
+
+namespace {
+const bool KKeyPress = true;
+const bool KKeyRelease = false;
+
+// Undefine define KeyRelease from X.h.
+// Enables using QEvent::KeyRelease type in eventFilter.
+#ifdef KeyRelease
+#undef KeyRelease
+#endif
+}
+
+Q_LOGGING_CATEGORY(lcHandleKeyEvents, "qt.virtualkeyboard.tests.manual.x11vkbwrapper.handlekeyevents")
+
+/**
+ * @brief qtKeyToXKeySym
+ * Mapping a Qt::Key to the KeySym.
+ * @param key a Pressed virtual key
+ * @param upper True if a Shift in use
+ * @return
+ */
+KeySym qtKeyToXKeySym(Qt::Key key, bool upper)
+{
+ const auto keySym = XStringToKeysym(QKeySequence(key).toString().toUtf8().data());
+ KeySym keyS = upper ? keySym : static_cast<unsigned long>(tolower(static_cast<int>(keySym)));
+ if (keyS != NoSymbol) {
+ return keyS;
+ }
+
+ for (int i = 0; KeyTbl[i] != 0; i += 2) {
+ if (KeyTbl[i + 1] == key) {
+ return KeyTbl[i];
+ }
+ }
+ return static_cast<ushort>(key);
+}
+
+/**
+ * @brief HandleKeyEvents::HandleKeyEvents
+ * Handling a key release events.
+ * @param parent
+ */
+HandleKeyEvents::HandleKeyEvents(QObject *parent) : QObject(parent),
+ m_xdo(nullptr)
+{
+
+}
+
+/**
+ * @brief HandleKeyEvents::~HandleKeyEvents
+ */
+HandleKeyEvents::~HandleKeyEvents()
+{
+ qCDebug(lcHandleKeyEvents) << Q_FUNC_INFO;
+ xdo_free(m_xdo);
+}
+
+/**
+ * @brief HandleKeyEvents::init
+ * @return false if xdo_new fail
+ */
+bool HandleKeyEvents::init()
+
+{
+ m_xdo = xdo_new(nullptr);
+ return m_xdo != nullptr;
+}
+
+/**
+ * @brief HandleKeyEvents::eventFilter
+ * Catch the QEvent::KeyRelease event.
+ * @param watched
+ * @param event a QEvent::KeyRelease
+ * @return
+ */
+bool HandleKeyEvents::eventFilter(QObject *watched, QEvent *event)
+{
+ Q_UNUSED( watched );
+
+ const auto type = event->type();
+ if (type == QEvent::MouseButtonRelease && !QGuiApplication::inputMethod()->isVisible()) {
+ // Start the VKB hide timer when the VKB indicator image is pressed.
+ VkbHideTimer::getInstance()->startTimer();
+ }
+ if (type == QEvent::MouseMove) {
+ // Start/re-start the VKB hide timer when there's mouse move event
+ // anywhere on the virtual keyboard surface.
+ VkbHideTimer::getInstance()->startTimer();
+ }
+ if (type == QEvent::MouseButtonPress) {
+ // Start/re-start the VKB hide timer when there's button press event
+ // anywhere on the virtual keyboard surface.
+ VkbHideTimer::getInstance()->startTimer();
+ }
+ if (type == QEvent::KeyRelease) {
+ if (m_xdo == nullptr) {
+ qWarning() << Q_FUNC_INFO << "xdo_t instance is not valid, shutting down...";
+ QApplication::exit(1);
+ }
+ // Start/re-start the VKB hide timer when the VKB keys are pressed.
+ VkbHideTimer::getInstance()->startTimer();
+
+ auto keyEvent = static_cast<QKeyEvent *>(event);
+ bool shiftOn = keyEvent->modifiers() == Qt::ShiftModifier;
+ auto key = static_cast<Qt::Key>(keyEvent->key());
+ QString str = keyEvent->text();
+ /** a Qt special keys. */
+ if (qtKeyCodes.indexOf(key) >= 0) {
+ xdo_send_keysequence_window(m_xdo, CURRENTWINDOW,
+ XKeysymToString(qtKeyToXKeySym(key, shiftOn)),
+ 2000);
+ /** a Key strings as Emojis ":-), <3". */
+ } else if (str.length() > 1) {
+ xdo_enter_text_window(m_xdo, CURRENTWINDOW,
+ str.toLatin1(),
+ 2000);
+ /** a Normal Keys. */
+ } else if (!str.isEmpty()) {
+ keyTap(str);
+ }
+ }
+ return false;
+}
+
+/**
+ * @brief HandleKeyEvents::keyTap
+ * @param key a Key as a string
+ */
+void HandleKeyEvents::keyTap(const QString &key) const
+{
+ qCDebug(lcHandleKeyEvents) << Q_FUNC_INFO;
+ bool shiftDown = false;
+ KeyCode keyCode = getUnicodeKeycode(key);
+ KeyCode shift = XKeysymToKeycode(m_xdo->xdpy, XK_Shift_L);
+ /** Press a Shift button down if capital letter. */
+ if (key.length() == 1 && (key.toLower() != key || xUpKeyCodes.count(key))) {
+ keyPressRelease(shift, KKeyPress);
+ shiftDown = true;
+ }
+
+ /** A Key press */
+ keyPressRelease(keyCode, KKeyPress);
+ /** A Key release */
+ keyPressRelease(keyCode, KKeyRelease);
+
+ /** Release a Shift button if capital letter. */
+ if (shiftDown) {
+ keyPressRelease(shift, KKeyRelease);
+ }
+}
+
+/**
+ * @brief HandleKeyEvents::keyPressRelease
+ * Press / Release a key
+ * @param key a Key as a string
+ * @param eventType true when press a key
+ */
+void HandleKeyEvents::keyPressRelease(const KeyCode key, const bool eventType) const
+{
+ qCDebug(lcHandleKeyEvents) << Q_FUNC_INFO;
+ XTestFakeKeyEvent(m_xdo->xdpy, key, eventType ? 1 : 0, 0);
+ XFlush(m_xdo->xdpy);
+}
+
+/**
+ * @brief HandleKeyEvents::getUnicodeKeycode
+ * Get a correct key mapping for a key.
+ * @param key a Key as a string
+ * @return Keycode
+ */
+KeyCode HandleKeyEvents::getUnicodeKeycode(const QString &key) const
+{
+ qCDebug(lcHandleKeyEvents) << Q_FUNC_INFO;
+ KeyCode code = 0;
+ if (xKeyCodes.count(key)) {
+ auto xKeyIter = xKeyCodes.find(key);
+ code = XKeysymToKeycode(m_xdo->xdpy, xKeyIter->second);
+ } else if (xUpKeyCodes.count(key)) {
+ auto xUpKeyIter = xKeyCodes.find(key);
+ code = XKeysymToKeycode(m_xdo->xdpy, xUpKeyIter->second);
+ } else {
+ auto unicodeIter = unicodeKeySymbols.find(key);
+ quint32 unicodeKey = unicodeIter != unicodeKeySymbols.end() ? unicodeIter->second : 0;
+ KeySym keysyms[] = {unicodeKey};
+ XChangeKeyboardMapping(m_xdo->xdpy, 999, 1, static_cast<KeySym*>(keysyms), 1);
+ code = static_cast<KeyCode>(999);
+ }
+ return code;
+}
+
diff --git a/tests/manual/x11vkbwrapper/handlekeyevents.h b/tests/manual/x11vkbwrapper/handlekeyevents.h
new file mode 100644
index 00000000..760ba757
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/handlekeyevents.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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 HANDLEKEYEVENTS_H
+#define HANDLEKEYEVENTS_H
+
+#include <QObject>
+
+class QKeyEvent;
+
+extern "C" {
+#include <xdo.h>
+}
+
+/**
+ * @brief The HandleKeyEvents class
+ * Handling key release events.
+ */
+class HandleKeyEvents : public QObject
+{
+ Q_OBJECT
+public:
+ explicit HandleKeyEvents(QObject *parent = nullptr);
+ ~HandleKeyEvents();
+
+ bool init();
+
+private:
+ void keyTap(const QString &key) const;
+ void keyPressRelease(const KeyCode key, const bool eventType) const;
+ KeyCode getUnicodeKeycode(const QString &key) const;
+
+protected:
+ /** Deliver events from a another object(s). */
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
+private:
+ /** Libxdo context. */
+ xdo_t *m_xdo;
+};
+
+#endif // HANDLEKEYEVENTS_H
diff --git a/tests/manual/x11vkbwrapper/handlelanguagechange.cpp b/tests/manual/x11vkbwrapper/handlelanguagechange.cpp
new file mode 100644
index 00000000..49c413c3
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/handlelanguagechange.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 <QLoggingCategory>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QFile>
+#include <QDir>
+
+#include "handlelanguagechange.h"
+
+namespace {
+const QString KFilePath = "/x11vkbwrapper_language/";
+const QString KFilePathName = KFilePath + "currentLang.json";
+}
+
+Q_LOGGING_CATEGORY(lcHandleLanguageChange, "qt.virtualkeyboard.tests.manual.x11vkbwrapper.handlelanguagechange")
+
+/**
+ * @brief HandleJson::HandleJson
+ * Class is only for testing purpose
+ * @param parent
+ */
+HandleLanguageChange::HandleLanguageChange(QObject *parent) : QObject(parent)
+{
+
+}
+
+/**
+ * @brief HandleLanguageChange::languageChanged
+ * Signal emitted on QML when a language is changed
+ * @param language
+ */
+void HandleLanguageChange::languageChanged(const QString &language) const
+{
+ qCDebug(lcHandleLanguageChange) << Q_FUNC_INFO << QDir::homePath();
+ QJsonDocument langDoc;
+ QJsonObject langObj;
+ langObj["language"] = language;
+ langDoc.setObject(langObj);
+
+ if (!QDir(QDir::homePath() + KFilePath).exists()) {
+ QDir dir;
+ dir.mkdir(QDir::homePath() + KFilePath);
+ }
+
+ QFile jsonFile(QDir::homePath() + KFilePathName);
+ jsonFile.open(QFile::WriteOnly);
+ jsonFile.write(langDoc.toJson());
+ jsonFile.flush();
+ jsonFile.close();
+}
diff --git a/tests/manual/x11vkbwrapper/handlelanguagechange.h b/tests/manual/x11vkbwrapper/handlelanguagechange.h
new file mode 100644
index 00000000..9600f006
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/handlelanguagechange.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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 HANDLELANGUAGECHANGE_H
+#define HANDLELANGUAGECHANGE_H
+
+#include <QObject>
+
+class HandleLanguageChange: public QObject
+{
+ Q_OBJECT
+
+public:
+ HandleLanguageChange(QObject *parent = nullptr);
+
+public slots:
+ void languageChanged(const QString &language) const;
+
+};
+
+#endif // HANDLELANGUAGECHANGE_H
diff --git a/tests/manual/x11vkbwrapper/keyboard.qml b/tests/manual/x11vkbwrapper/keyboard.qml
new file mode 100644
index 00000000..02d93769
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/keyboard.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Window 2.2
+import QtQuick.VirtualKeyboard 2.2
+
+Window {
+ id: keyboardWindow
+ width: Screen.width / scaleFactor
+ height: inputPanel.height + d.alternativeKeySpaceHeight
+ color: "transparent"
+ visible: Qt.inputMethod.visible
+ flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.FramelessWindowHint
+
+ readonly property double scaleFactor: 1.5
+ signal languageChangedSignal(string msg)
+
+ QtObject {
+ id: d
+ property double alternativeKeySpaceHeight: inputPanel.height / 4.5
+ }
+
+ Loader {
+ id: testLoader
+ sourceComponent: {
+ if (typeof(QT_TESTING_RUN) !== undefined) {
+ lang
+ }
+ }
+ }
+
+ Component {
+ id: lang
+ Text {
+ id: langText
+ visible: false
+ text: qsTr(Qt.locale(InputContext.locale).nativeLanguageName)
+ onTextChanged: {
+ keyboardWindow.languageChangedSignal(langText.text)
+ }
+ }
+ }
+
+ InputPanel {
+ id: inputPanel
+ z: 99
+ width: keyboardWindow.width
+ anchors.bottom: parent.bottom
+ }
+}
diff --git a/tests/manual/x11vkbwrapper/keysymmapsforfakeinput.h b/tests/manual/x11vkbwrapper/keysymmapsforfakeinput.h
new file mode 100644
index 00000000..7dc404ba
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/keysymmapsforfakeinput.h
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** 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 <QString>
+#include <QList>
+#include <map>
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/extensions/XTest.h>
+#include <X11/keysym.h>
+#include <X11/XF86keysym.h>
+#include <ctime>
+}
+
+static const std::map<QString, quint32> unicodeKeySymbols {
+ {"!",0x0021}, {"\"",0x0022}, {"#",0x0023}, {"$",0x0024}, {"%",0x0025}, {"&",0x0026}, {"'",0x0027},
+ {"(",0x0028}, {")",0x0029}, {"*",0x002A}, {"+",0x002B}, {",",0x002C}, {"-",0x002D}, {".",0x002E},
+ {"/",0x002F},
+ {"0",0x0030}, {"1",0x0031}, {"2",0x0032}, {"3",0x0033}, {"4",0x0034}, {"5",0x0035},
+ {"6",0x0036}, {"7",0x0037}, {"8",0x0038}, {"9",0x0039},
+ {":",0x003A}, {";",0x003B}, {"<",0x003C},
+ {"=",0x003D}, {">",0x003E}, {"?",0x003F}, {"@",0x0040},
+ {"A",0x0041}, {"B",0x0042}, {"C",0x0043},
+ {"D",0x0044}, {"E",0x0045}, {"F",0x0046}, {"G",0x0047}, {"H",0x0048}, {"I",0x0049}, {"J",0x004A},
+ {"K",0x004B}, {"L",0x004C}, {"M",0x004D}, {"N",0x004E}, {"O",0x004F}, {"P",0x0050}, {"Q",0x0051},
+ {"R",0x0052}, {"S",0x0053}, {"T",0x0054}, {"U",0x0055}, {"V",0x0056}, {"W",0x0057}, {"X",0x0058},
+ {"Y",0x0059}, {"Z",0x005A},
+ {"[",0x005B}, {"\\",0x005C}, {"]",0x005D}, {"^",0x005E}, {"_",0x005F},
+ {"`",0x0060},
+ {"a",0x0061}, {"b",0x0062}, {"c",0x0063}, {"d",0x0064}, {"e",0x0065}, {"f",0x0066},
+ {"g",0x0067}, {"h",0x0068}, {"i",0x0069}, {"j",0x006A}, {"k",0x006B}, {"l",0x006C}, {"m",0x006D},
+ {"n",0x006E}, {"o",0x006F}, {"p",0x0070}, {"q",0x0071}, {"r",0x0072}, {"s",0x0073}, {"t",0x0074},
+ {"u",0x0075}, {"v",0x0076}, {"w",0x0077}, {"x",0x0078}, {"y",0x0079}, {"z",0x007A}, {"{",0x007B},
+ {"|",0x007C}, {"}",0x007D}, {"~",0x007E}, {" ",0x00A0}, {"¡",0x00A1}, {"¢",0x00A2}, {"£",0x00A3},
+ {"¤",0x00A4}, {"¥",0x00A5}, {"¦",0x00A6}, {"§",0x00A7}, {"¨",0x00A8}, {"©",0x00A9}, {"ª",0x00AA},
+ {"«",0x00AB}, {"¬",0x00AC}, {"­",0x00AD}, {"®",0x00AE}, {"¯",0x00AF}, {"°",0x00B0}, {"±",0x00B1},
+ {"²",0x00B2}, {"³",0x00B3}, {"´",0x00B4}, {"µ",0x00B5}, {"¶",0x00B6}, {"·",0x00B7}, {"¸",0x00B8},
+ {"¹",0x00B9}, {"º",0x00BA}, {"»",0x00BB}, {"¼",0x00BC}, {"½",0x00BD}, {"¾",0x00BE},
+ {"¿",0x00BF},
+ {"À",0x00C0}, {"Á",0x00C1}, {"Â",0x00C2}, {"Ã",0x00C3}, {"Ä",0x00C4}, {"Å",0x00C5}, {"Æ",0x00C6},
+ {"Ç",0x00C7}, {"È",0x00C8}, {"É",0x00C9}, {"Ê",0x00CA}, {"Ë",0x00CB}, {"Ì",0x00CC}, {"Í",0x00CD},
+ {"Î",0x00CE}, {"Ï",0x00CF}, {"Ð",0x00D0}, {"Ñ",0x00D1}, {"Ò",0x00D2}, {"Ó",0x00D3}, {"Ô",0x00D4},
+ {"Õ",0x00D5}, {"Ö",0x00D6}, {"×",0x00D7}, {"Ø",0x00D8}, {"Ù",0x00D9}, {"Ú",0x00DA}, {"Û",0x00DB},
+ {"Ü",0x00DC}, {"Ý",0x00DD}, {"Þ",0x00DE}, {"ß",0x00DF}, {"à",0x00E0}, {"á",0x00E1}, {"â",0x00E2},
+ {"ã",0x00E3}, {"ä",0x00E4}, {"å",0x00E5}, {"æ",0x00E6}, {"ç",0x00E7}, {"è",0x00E8}, {"é",0x00E9},
+ {"ê",0x00EA}, {"ë",0x00EB}, {"ì",0x00EC}, {"í",0x00ED}, {"î",0x00EE}, {"ï",0x00EF}, {"ð",0x00F0},
+ {"ñ",0x00F1}, {"ò",0x00F2}, {"ó",0x00F3}, {"ô",0x00F4}, {"õ",0x00F5}, {"ö",0x00F6}, {"÷",0x00F7},
+ {"ø",0x00F8}, {"ù",0x00F9}, {"ú",0x00FA}, {"û",0x00FB}, {"ü",0x00FC}, {"ý",0x00FD}, {"þ",0x00FE},
+ {"ÿ",0x00FF}, {"Ą",0x01A1}, {"˘",0x01A2}, {"Ł",0x01A3}, {"Ľ",0x01A5}, {"Ś",0x01A6}, {"Š",0x01A9},
+ {"Ş",0x01AA}, {"Ť",0x01AB}, {"Ź",0x01AC}, {"Ž",0x01AE}, {"Ż",0x01AF}, {"ą",0x01B1}, {"˛",0x01B2},
+ {"ł",0x01B3}, {"ľ",0x01B5}, {"ś",0x01B6}, {"ˇ",0x01B7}, {"š",0x01B9}, {"ş",0x01BA}, {"ť",0x01BB},
+ {"ź",0x01BC}, {"˝",0x01BD}, {"ž",0x01BE}, {"ż",0x01BF}, {"Ŕ",0x01C0}, {"Ă",0x01C3}, {"Ĺ",0x01C5},
+ {"Ć",0x01C6}, {"Č",0x01C8}, {"Ę",0x01CA}, {"Ě",0x01CC}, {"Ď",0x01CF}, {"Đ",0x01D0}, {"Ń",0x01D1},
+ {"Ň",0x01D2}, {"Ő",0x01D5}, {"Ř",0x01D8}, {"Ů",0x01D9}, {"Ű",0x01DB}, {"Ţ",0x01DE}, {"ŕ",0x01E0},
+ {"ă",0x01E3}, {"ĺ",0x01E5}, {"ć",0x01E6}, {"č",0x01E8}, {"ę",0x01EA}, {"ě",0x01EC}, {"ď",0x01EF},
+ {"đ",0x01F0}, {"ń",0x01F1}, {"ň",0x01F2}, {"ő",0x01F5}, {"ř",0x01F8}, {"ů",0x01F9}, {"ű",0x01FB},
+ {"ţ",0x01FE}, {"˙",0x01FF}, {"Ħ",0x02A1}, {"Ĥ",0x02A6}, {"İ",0x02A9}, {"Ğ",0x02AB}, {"Ĵ",0x02AC},
+ {"ħ",0x02B1}, {"ĥ",0x02B6}, {"ı",0x02B9}, {"ğ",0x02BB}, {"ĵ",0x02BC}, {"Ċ",0x02C5}, {"Ĉ",0x02C6},
+ {"Ġ",0x02D5}, {"Ĝ",0x02D8}, {"Ŭ",0x02DD}, {"?Ŝ",0x02DE}, {"ċ",0x02E5}, {"ĉ",0x02E6}, {"ġ",0x02F5},
+ {"ĝ",0x02F8}, {"ŭ",0x02FD}, {"ŝ",0x02FE}, {"ĸ",0x03A2}, {"Ŗ",0x03A3}, {"Ĩ",0x03A5}, {"Ļ",0x03A6},
+ {"Ē",0x03AA}, {"Ģ",0x03AB}, {"Ŧ",0x03AC}, {"ŗ",0x03B3}, {"ĩ",0x03B5}, {"ļ",0x03B6}, {"ē",0x03BA},
+ {"ģ",0x03BB}, {"ŧ",0x03BC}, {"Ŋ",0x03BD}, {"ŋ",0x03BF}, {"Ā",0x03C0}, {"Į",0x03C7}, {"Ė",0x03CC},
+ {"Ī",0x03CF}, {"Ņ",0x03D1}, {"Ō",0x03D2}, {"Ķ",0x03D3}, {"Ų",0x03D9}, {"Ũ",0x03DD}, {"Ū",0x03DE},
+ {"ā",0x03E0}, {"į",0x03E7}, {"ė",0x03EC}, {"ī",0x03EF}, {"ņ",0x03F1}, {"ō",0x03F2}, {"ķ",0x03F3},
+ {"ų",0x03F9}, {"ũ",0x03FD}, {"ū",0x03FE}, {"‾",0x047E}, {"。",0x04A1}, {"「",0x04A2}, {"」",0x04A3},
+ {"、",0x04A4}, {"・",0x04A5}, {"ヲ",0x04A6}, {"ァ",0x04A7}, {"ィ",0x04A8}, {"ゥ",0x04A9}, {"ェ",0x04AA},
+ {"ォ",0x04AB}, {"ャ",0x04AC}, {"ュ",0x04AD}, {"ョ",0x04AE}, {"ッ",0x04AF}, {"ー",0x04B0}, {"ア",0x04B1},
+ {"イ",0x04B2}, {"ウ",0x04B3}, {"エ",0x04B4}, {"オ",0x04B5}, {"カ",0x04B6}, {"キ",0x04B7}, {"ク",0x04B8},
+ {"ケ",0x04B9}, {"コ",0x04BA}, {"サ",0x04BB}, {"シ",0x04BC}, {"ス",0x04BD}, {"セ",0x04BE}, {"ソ",0x04BF},
+ {"タ",0x04C0}, {"チ",0x04C1}, {"ツ",0x04C2}, {"テ",0x04C3}, {"ト",0x04C4}, {"ナ",0x04C5}, {"ニ",0x04C6},
+ {"ヌ",0x04C7}, {"ネ",0x04C8}, {"ノ",0x04C9}, {"ハ",0x04CA}, {"ヒ",0x04CB}, {"フ",0x04CC}, {"ヘ",0x04CD},
+ {"ホ",0x04CE}, {"マ",0x04CF}, {"ミ",0x04D0}, {"ム",0x04D1}, {"メ",0x04D2}, {"モ",0x04D3}, {"ヤ",0x04D4},
+ {"ユ",0x04D5}, {"ヨ",0x04D6}, {"ラ",0x04D7}, {"リ",0x04D8}, {"ル",0x04D9}, {"レ",0x04DA}, {"ロ",0x04DB},
+ {"ワ",0x04DC}, {"ン",0x04DD}, {"゛",0x04DE}, {"゜",0x04DF}, {"۰",0x0590}, {"۱",0x0591}, {"۲",0x0592},
+ {"۳",0x0593}, {"۴",0x0594}, {"۵",0x0595}, {"۶",0x0596}, {"۷",0x0597}, {"۸",0x0598}, {"۹",0x0599},
+ {"٪",0x05A5}, {"ٰ",0x05A6}, {"ٹ",0x05A7}, {"پ",0x05A8}, {"چ",0x05A9}, {"ڈ",0x05AA}, {"ڑ",0x05AB},
+ {"،",0x05AC}, {"۔",0x05AE}, {"٠",0x05B0}, {"١",0x05B1}, {"٢",0x05B2}, {"٣",0x05B3}, {"٤",0x05B4},
+ {"٥",0x05B5}, {"٦",0x05B6}, {"٧",0x05B7}, {"٨",0x05B8}, {"٩",0x05B9}, {"؛",0x05BB}, {"؟",0x05BF},
+ {"ء",0x05C1}, {"آ",0x05C2}, {"أ",0x05C3}, {"ؤ",0x05C4}, {"إ",0x05C5}, {"ئ",0x05C6}, {"ا",0x05C7},
+ {"ب",0x05C8}, {"ة",0x05C9}, {"ت",0x05CA}, {"ث",0x05CB}, {"ج",0x05CC}, {"ح",0x05CD}, {"خ",0x05CE},
+ {"د",0x05CF}, {"ذ",0x05D0}, {"ر",0x05D1}, {"ز",0x05D2}, {"س",0x05D3}, {"ش",0x05D4}, {"ص",0x05D5},
+ {"ض",0x05D6}, {"ط",0x05D7}, {"ظ",0x05D8}, {"ع",0x05D9}, {"غ",0x05DA}, {"ـ",0x05E0}, {"ف",0x05E1},
+ {"ق",0x05E2}, {"ك",0x05E3}, {"ل",0x05E4}, {"م",0x05E5}, {"ن",0x05E6}, {"ه",0x05E7}, {"و",0x05E8},
+ {"ى",0x05E9}, {"ي",0x05EA}, {"ً",0x05EB}, {"ٌ",0x05EC}, {"ٍ",0x05ED}, {"َ",0x05EE}, {"ُ",0x05EF},
+ {"ِ",0x05F0}, {"ّ",0x05F1}, {"ْ",0x05F2}, {"ٓ",0x05F3}, {"ٔ",0x05F4}, {"ٕ",0x05F5}, {"ژ",0x05F6},
+ {"ڤ",0x05F7}, {"ک",0x05F8}, {"گ",0x05F9}, {"ں",0x05FA}, {"ھ",0x05FB}, {"ی",0x05FC}, {"ے",0x05FD},
+ {"ہ",0x05FE}, {"Ғ",0x0680}, {"Җ",0x0681}, {"Қ",0x0682}, {"Ҝ",0x0683}, {"Ң",0x0684}, {"Ү",0x0685},
+ {"Ұ",0x0686}, {"Ҳ",0x0687}, {"Ҷ",0x0688}, {"Ҹ",0x0689}, {"Һ",0x068A}, {"Ә",0x068C}, {"Ӣ",0x068D},
+ {"Ө",0x068E}, {"Ӯ",0x068F}, {"ғ",0x0690}, {"җ",0x0691}, {"қ",0x0692}, {"ҝ",0x0693}, {"ң",0x0694},
+ {"ү",0x0695}, {"ұ",0x0696}, {"ҳ",0x0697}, {"ҷ",0x0698}, {"ҹ",0x0699}, {"һ",0x069A}, {"ә",0x069C},
+ {"ӣ",0x069D}, {"ө",0x069E}, {"ӯ",0x069F}, {"ђ",0x06A1}, {"ѓ",0x06A2}, {"ё",0x06A3}, {"є",0x06A4},
+ {"ѕ",0x06A5}, {"і",0x06A6}, {"ї",0x06A7}, {"ј",0x06A8}, {"љ",0x06A9}, {"њ",0x06AA}, {"ћ",0x06AB},
+ {"ќ",0x06AC}, {"ґ",0x06AD}, {"ў",0x06AE}, {"џ",0x06AF}, {"№",0x06B0}, {"Ђ",0x06B1}, {"Ѓ",0x06B2},
+ {"Ё",0x06B3}, {"Є",0x06B4}, {"Ѕ",0x06B5}, {"І",0x06B6}, {"Ї",0x06B7}, {"Ј",0x06B8}, {"Љ",0x06B9},
+ {"Њ",0x06BA}, {"Ћ",0x06BB}, {"Ќ",0x06BC}, {"Ґ",0x06BD}, {"Ў",0x06BE}, {"Џ",0x06BF}, {"ю",0x06C0},
+ {"а",0x06C1}, {"б",0x06C2}, {"ц",0x06C3}, {"д",0x06C4}, {"е",0x06C5}, {"ф",0x06C6}, {"г",0x06C7},
+ {"х",0x06C8}, {"и",0x06C9}, {"й",0x06CA}, {"к",0x06CB}, {"л",0x06CC}, {"м",0x06CD}, {"н",0x06CE},
+ {"о",0x06CF}, {"п",0x06D0}, {"я",0x06D1}, {"р",0x06D2}, {"с",0x06D3}, {"т",0x06D4}, {"у",0x06D5},
+ {"ж",0x06D6}, {"в",0x06D7}, {"ь",0x06D8}, {"ы",0x06D9}, {"з",0x06DA}, {"ш",0x06DB}, {"э",0x06DC},
+ {"щ",0x06DD}, {"ч",0x06DE}, {"ъ",0x06DF}, {"Ю",0x06E0}, {"А",0x06E1}, {"Б",0x06E2}, {"Ц",0x06E3},
+ {"Д",0x06E4}, {"Е",0x06E5}, {"Ф",0x06E6}, {"Г",0x06E7}, {"Х",0x06E8}, {"И",0x06E9}, {"Й",0x06EA},
+ {"К",0x06EB}, {"Л",0x06EC}, {"М",0x06ED}, {"Н",0x06EE}, {"О",0x06EF}, {"П",0x06F0}, {"Я",0x06F1},
+ {"Р",0x06F2}, {"С",0x06F3}, {"Т",0x06F4}, {"У",0x06F5}, {"Ж",0x06F6}, {"В",0x06F7}, {"Ь",0x06F8},
+ {"Ы",0x06F9}, {"З",0x06FA}, {"Ш",0x06FB}, {"Э",0x06FC}, {"Щ",0x06FD}, {"Ч",0x06FE}, {"Ъ",0x06FF},
+ {"Ά",0x07A1}, {"Έ",0x07A2}, {"Ή",0x07A3}, {"Ί",0x07A4}, {"Ϊ",0x07A5}, {"Ό",0x07A7}, {"Ύ",0x07A8},
+ {"Ϋ",0x07A9}, {"Ώ",0x07AB}, {"΅",0x07AE}, {"―",0x07AF}, {"ά",0x07B1}, {"έ",0x07B2}, {"ή",0x07B3},
+ {"ί",0x07B4}, {"ϊ",0x07B5}, {"ΐ",0x07B6}, {"ό",0x07B7}, {"ύ",0x07B8}, {"ϋ",0x07B9}, {"ΰ",0x07BA},
+ {"ώ",0x07BB}, {"Α",0x07C1}, {"Β",0x07C2}, {"Γ",0x07C3}, {"Δ",0x07C4}, {"Ε",0x07C5}, {"Ζ",0x07C6},
+ {"Η",0x07C7}, {"Θ",0x07C8}, {"Ι",0x07C9}, {"Κ",0x07CA}, {"Λ",0x07CB}, {"Μ",0x07CC}, {"Ν",0x07CD},
+ {"Ξ",0x07CE}, {"Ο",0x07CF}, {"Π",0x07D0}, {"Ρ",0x07D1}, {"Σ",0x07D2}, {"Τ",0x07D4}, {"Υ",0x07D5},
+ {"Φ",0x07D6}, {"Χ",0x07D7}, {"Ψ",0x07D8}, {"Ω",0x07D9}, {"α",0x07E1}, {"β",0x07E2}, {"γ",0x07E3},
+ {"δ",0x07E4}, {"ε",0x07E5}, {"ζ",0x07E6}, {"η",0x07E7}, {"θ",0x07E8}, {"ι",0x07E9}, {"κ",0x07EA},
+ {"λ",0x07EB}, {"μ",0x07EC}, {"ν",0x07ED}, {"ξ",0x07EE}, {"ο",0x07EF}, {"π",0x07F0}, {"ρ",0x07F1},
+ {"σ",0x07F2}, {"ς",0x07F3}, {"τ",0x07F4}, {"υ",0x07F5}, {"φ",0x07F6}, {"χ",0x07F7}, {"ψ",0x07F8},
+ {"ω",0x07F9}, {"⎷",0x08A1}, {"┌",0x08A2}, {"─",0x08A3}, {"⌠",0x08A4}, {"⌡",0x08A5}, {"│",0x08A6},
+ {"⎡",0x08A7}, {"⎣",0x08A8}, {"⎤",0x08A9}, {"⎦",0x08AA}, {"⎛",0x08AB}, {"⎝",0x08AC}, {"⎞",0x08AD},
+ {"⎠",0x08AE}, {"⎨",0x08AF}, {"⎬",0x08B0}, {"≤",0x08BC}, {"≠",0x08BD}, {"≥",0x08BE}, {"∫",0x08BF},
+ {"∴",0x08C0}, {"∝",0x08C1}, {"∞",0x08C2}, {"∇",0x08C5}, {"∼",0x08C8}, {"≃",0x08C9}, {"⇔",0x08CD},
+ {"⇒",0x08CE}, {"≡",0x08CF}, {"√",0x08D6}, {"⊂",0x08DA}, {"⊃",0x08DB}, {"∩",0x08DC}, {"∪",0x08DD},
+ {"∧",0x08DE}, {"∨",0x08DF}, {"∂",0x08EF}, {"ƒ",0x08F6}, {"←",0x08FB}, {"↑",0x08FC}, {"→",0x08FD},
+ {"↓",0x08FE}, {"◆",0x09E0}, {"▒",0x09E1}, {"␉",0x09E2}, {"␌",0x09E3}, {"␍",0x09E4}, {"␊",0x09E5},
+ {"␤",0x09E8}, {"␋",0x09E9}, {"┘",0x09EA}, {"┐",0x09EB}, {"┌",0x09EC}, {"└",0x09ED}, {"┼",0x09EE},
+ {"⎺",0x09EF}, {"⎻",0x09F0}, {"─",0x09F1}, {"⎼",0x09F2}, {"⎽",0x09F3}, {"├",0x09F4}, {"┤",0x09F5},
+ {"┴",0x09F6}, {"┬",0x09F7}, {"│",0x09F8}, {" ",0x0AA1}, {" ",0x0AA2}, {" ",0x0AA3}, {" ",0x0AA4},
+ {" ",0x0AA5}, {" ",0x0AA6}, {" ",0x0AA7}, {" ",0x0AA8}, {"—",0x0AA9}, {"–",0x0AAA}, {"␣",0x0AAC},
+ {"…",0x0AAE}, {"‥",0x0AAF}, {"⅓",0x0AB0}, {"⅔",0x0AB1}, {"⅕",0x0AB2}, {"⅖",0x0AB3}, {"⅗",0x0AB4},
+ {"⅘",0x0AB5}, {"⅙",0x0AB6}, {"⅚",0x0AB7}, {"℅",0x0AB8}, {"‒",0x0ABB}, {"⟨",0x0ABC}, {".",0x0ABD},
+ {"⟩",0x0ABE}, {"⅛",0x0AC3}, {"⅜",0x0AC4}, {"⅝",0x0AC5}, {"⅞",0x0AC6}, {"™",0x0AC9}, {"☓",0x0ACA},
+ {"◁",0x0ACC}, {"▷",0x0ACD}, {"○",0x0ACE}, {"▯",0x0ACF}, {"‘",0x0AD0}, {"’",0x0AD1}, {"“",0x0AD2},
+ {"”",0x0AD3}, {"℞",0x0AD4}, {"′",0x0AD6}, {"″",0x0AD7}, {"✝",0x0AD9}, {"▬",0x0ADB}, {"◀",0x0ADC},
+ {"▶",0x0ADD}, {"●",0x0ADE}, {"▮",0x0ADF}, {"◦",0x0AE0}, {"▫",0x0AE1}, {"▭",0x0AE2}, {"△",0x0AE3},
+ {"▽",0x0AE4}, {"☆",0x0AE5}, {"•",0x0AE6}, {"▪",0x0AE7}, {"▲",0x0AE8}, {"▼",0x0AE9}, {"☜",0x0AEA},
+ {"☞",0x0AEB}, {"♣",0x0AEC}, {"♦",0x0AED}, {"♥",0x0AEE}, {"✠",0x0AF0}, {"†",0x0AF1}, {"‡",0x0AF2},
+ {"✓",0x0AF3}, {"✗",0x0AF4}, {"♯",0x0AF5}, {"♭",0x0AF6}, {"♂",0x0AF7}, {"♀",0x0AF8}, {"☎",0x0AF9},
+ {"⌕",0x0AFA}, {"℗",0x0AFB}, {"‸",0x0AFC}, {"‚",0x0AFD}, {"„",0x0AFE}, {"<",0x0BA3}, {">",0x0BA6},
+ {"∨",0x0BA8}, {"∧",0x0BA9}, {"¯",0x0BC0}, {"⊥",0x0BC2}, {"∩",0x0BC3}, {"⌊",0x0BC4}, {"_",0x0BC6},
+ {"∘",0x0BCA}, {"⎕",0x0BCC}, {"⊤",0x0BCE}, {"○",0x0BCF}, {"⌈",0x0BD3}, {"∪",0x0BD6}, {"⊃",0x0BD8},
+ {"⊂",0x0BDA}, {"⊢",0x0BDC}, {"⊣",0x0BFC}, {"‗",0x0CDF}, {"א",0x0CE0}, {"ב",0x0CE1}, {"ג",0x0CE2},
+ {"ד",0x0CE3}, {"ה",0x0CE4}, {"ו",0x0CE5}, {"ז",0x0CE6}, {"ח",0x0CE7}, {"ט",0x0CE8}, {"י",0x0CE9},
+ {"ך",0x0CEA}, {"כ",0x0CEB}, {"ל",0x0CEC}, {"ם",0x0CED}, {"מ",0x0CEE}, {"ן",0x0CEF}, {"נ",0x0CF0},
+ {"ס",0x0CF1}, {"ע",0x0CF2}, {"ף",0x0CF3}, {"פ",0x0CF4}, {"ץ",0x0CF5}, {"צ",0x0CF6}, {"ק",0x0CF7},
+ {"ר",0x0CF8}, {"ש",0x0CF9}, {"ת",0x0CFA}, {"ก",0x0DA1}, {"ข",0x0DA2}, {"ฃ",0x0DA3}, {"ค",0x0DA4},
+ {"ฅ",0x0DA5}, {"ฆ",0x0DA6}, {"ง",0x0DA7}, {"จ",0x0DA8}, {"ฉ",0x0DA9}, {"ช",0x0DAA}, {"ซ",0x0DAB},
+ {"ฌ",0x0DAC}, {"ญ",0x0DAD}, {"ฎ",0x0DAE}, {"ฏ",0x0DAF}, {"ฐ",0x0DB0}, {"ฑ",0x0DB1}, {"ฒ",0x0DB2},
+ {"ณ",0x0DB3}, {"ด",0x0DB4}, {"ต",0x0DB5}, {"ถ",0x0DB6}, {"ท",0x0DB7}, {"ธ",0x0DB8}, {"น",0x0DB9},
+ {"บ",0x0DBA}, {"ป",0x0DBB}, {"ผ",0x0DBC}, {"ฝ",0x0DBD}, {"พ",0x0DBE}, {"ฟ",0x0DBF}, {"ภ",0x0DC0},
+ {"ม",0x0DC1}, {"ย",0x0DC2}, {"ร",0x0DC3}, {"ฤ",0x0DC4}, {"ล",0x0DC5}, {"ฦ",0x0DC6}, {"ว",0x0DC7},
+ {"ศ",0x0DC8}, {"ษ",0x0DC9}, {"ส",0x0DCA}, {"ห",0x0DCB}, {"ฬ",0x0DCC}, {"อ",0x0DCD}, {"ฮ",0x0DCE},
+ {"ฯ",0x0DCF}, {"ะ",0x0DD0}, {"ั",0x0DD1}, {"า",0x0DD2}, {"ำ",0x0DD3}, {"ิ",0x0DD4}, {"ี",0x0DD5},
+ {"ึ",0x0DD6}, {"ื",0x0DD7}, {"ุ",0x0DD8}, {"ู",0x0DD9}, {"ฺ",0x0DDA}, {"฿",0x0DDF}, {"เ",0x0DE0},
+ {"แ",0x0DE1}, {"โ",0x0DE2}, {"ใ",0x0DE3}, {"ไ",0x0DE4}, {"ๅ",0x0DE5}, {"ๆ",0x0DE6}, {"็",0x0DE7},
+ {"่",0x0DE8}, {"้",0x0DE9}, {"๊",0x0DEA}, {"๋",0x0DEB}, {"์",0x0DEC}, {"ํ",0x0DED}, {"๐",0x0DF0}, {"๑",0x0DF1},
+ {"๒",0x0DF2}, {"๓",0x0DF3}, {"๔",0x0DF4}, {"๕",0x0DF5}, {"๖",0x0DF6}, {"๗",0x0DF7}, {"๘",0x0DF8},
+ {"๙",0x0DF9}, {"ㄱ",0x0EA1}, {"ㄲ",0x0EA2}, {"ㄳ",0x0EA3}, {"ㄴ",0x0EA4}, {"ㄵ",0x0EA5}, {"ㄶ",0x0EA6},
+ {"ㄷ",0x0EA7}, {"ㄸ",0x0EA8}, {"ㄹ",0x0EA9}, {"ㄺ",0x0EAA}, {"ㄻ",0x0EAB}, {"ㄼ",0x0EAC}, {"ㄽ",0x0EAD},
+ {"ㄾ",0x0EAE}, {"ㄿ",0x0EAF}, {"ㅀ",0x0EB0}, {"ㅁ",0x0EB1}, {"ㅂ",0x0EB2}, {"ㅃ",0x0EB3}, {"ㅄ",0x0EB4},
+ {"ㅅ",0x0EB5}, {"ㅆ",0x0EB6}, {"ㅇ",0x0EB7}, {"ㅈ",0x0EB8}, {"ㅉ",0x0EB9}, {"ㅊ",0x0EBA}, {"ㅋ",0x0EBB},
+ {"ㅌ",0x0EBC}, {"ㅍ",0x0EBD}, {"ㅎ",0x0EBE}, {"ㅏ",0x0EBF}, {"ㅐ",0x0EC0}, {"ㅑ",0x0EC1}, {"ㅒ",0x0EC2},
+ {"ㅓ",0x0EC3}, {"ㅔ",0x0EC4}, {"ㅕ",0x0EC5}, {"ㅖ",0x0EC6}, {"ㅗ",0x0EC7}, {"ㅘ",0x0EC8}, {"ㅙ",0x0EC9},
+ {"ㅚ",0x0ECA}, {"ㅛ",0x0ECB}, {"ㅜ",0x0ECC}, {"ㅝ",0x0ECD}, {"ㅞ",0x0ECE}, {"ㅟ",0x0ECF}, {"ㅠ",0x0ED0},
+ {"ㅡ",0x0ED1}, {"ㅢ",0x0ED2}, {"ㅣ",0x0ED3}, {"ᆨ",0x0ED4}, {"ᆩ",0x0ED5}, {"ᆪ",0x0ED6}, {"ᆫ",0x0ED7},
+ {"ᆬ",0x0ED8}, {"ᆭ",0x0ED9}, {"ᆮ",0x0EDA}, {"ᆯ",0x0EDB}, {"ᆰ",0x0EDC}, {"ᆱ",0x0EDD}, {"ᆲ",0x0EDE},
+ {"ᆳ",0x0EDF}, {"ᆴ",0x0EE0}, {"ᆵ",0x0EE1}, {"ᆶ",0x0EE2}, {"ᆷ",0x0EE3}, {"ᆸ",0x0EE4}, {"ᆹ",0x0EE5},
+ {"ᆺ",0x0EE6}, {"ᆻ",0x0EE7}, {"ᆼ",0x0EE8}, {"ᆽ",0x0EE9}, {"ᆾ",0x0EEA}, {"ᆿ",0x0EEB}, {"ᇀ",0x0EEC},
+ {"ᇁ",0x0EED}, {"ᇂ",0x0EEE}, {"ㅭ",0x0EEF}, {"ㅱ",0x0EF0}, {"ㅸ",0x0EF1}, {"ㅿ",0x0EF2}, {"ㆁ",0x0EF3},
+ {"ㆄ",0x0EF4}, {"ㆆ",0x0EF5}, {"ㆍ",0x0EF6}, {"ㆎ",0x0EF7}, {"ᇫ",0x0EF8}, {"ᇰ",0x0EF9}, {"ᇹ",0x0EFA},
+ {"₩",0x0EFF}, {"Ḃ",0x12A1}, {"ḃ",0x12A2}, {"Ḋ",0x12A6}, {"Ẁ",0x12A8}, {"Ẃ",0x12AA}, {"ḋ",0x12AB},
+ {"Ỳ",0x12AC}, {"Ḟ",0x12B0}, {"ḟ",0x12B1}, {"Ṁ",0x12B4}, {"ṁ",0x12B5}, {"Ṗ",0x12B7}, {"ẁ",0x12B8},
+ {"ṗ",0x12B9}, {"ẃ",0x12BA}, {"Ṡ",0x12BB}, {"ỳ",0x12BC}, {"Ẅ",0x12BD}, {"ẅ",0x12BE}, {"ṡ",0x12BF},
+ {"Ŵ",0x12D0}, {"Ṫ",0x12D7}, {"Ŷ",0x12DE}, {"ŵ",0x12F0}, {"ṫ",0x12F7}, {"ŷ",0x12FE}, {"Œ",0x13BC},
+ {"œ",0x13BD}, {"Ÿ",0x13BE}, {"և",0x14A2}, {"։",0x14A3}, {")",0x14A4}, {"(",0x14A5}, {"»",0x14A6},
+ {"«",0x14A7}, {"—",0x14A8}, {".",0x14A9}, {"՝",0x14AA}, {",",0x14AB}, {"–",0x14AC}, {"֊",0x14AD},
+ {"…",0x14AE}, {"՜",0x14AF}, {"՛",0x14B0}, {"՞",0x14B1}, {"Ա",0x14B2}, {"ա",0x14B3}, {"Բ",0x14B4},
+ {"բ",0x14B5}, {"Գ",0x14B6}, {"գ",0x14B7}, {"Դ",0x14B8}, {"դ",0x14B9}, {"Ե",0x14BA}, {"ե",0x14BB},
+ {"Զ",0x14BC}, {"զ",0x14BD}, {"Է",0x14BE}, {"է",0x14BF}, {"Ը",0x14C0}, {"ը",0x14C1}, {"Թ",0x14C2},
+ {"թ",0x14C3}, {"Ժ",0x14C4}, {"ժ",0x14C5}, {"Ի",0x14C6}, {"ի",0x14C7}, {"Լ",0x14C8}, {"լ",0x14C9},
+ {"Խ",0x14CA}, {"խ",0x14CB}, {"Ծ",0x14CC}, {"ծ",0x14CD}, {"Կ",0x14CE}, {"կ",0x14CF}, {"Հ",0x14D0},
+ {"հ",0x14D1}, {"Ձ",0x14D2}, {"ձ",0x14D3}, {"Ղ",0x14D4}, {"ղ",0x14D5}, {"Ճ",0x14D6}, {"ճ",0x14D7},
+ {"Մ",0x14D8}, {"մ",0x14D9}, {"Յ",0x14DA}, {"յ",0x14DB}, {"Ն",0x14DC}, {"ն",0x14DD}, {"Շ",0x14DE},
+ {"շ",0x14DF}, {"Ո",0x14E0}, {"ո",0x14E1}, {"Չ",0x14E2}, {"չ",0x14E3}, {"Պ",0x14E4}, {"պ",0x14E5},
+ {"Ջ",0x14E6}, {"ջ",0x14E7}, {"Ռ",0x14E8}, {"ռ",0x14E9}, {"Ս",0x14EA}, {"ս",0x14EB}, {"Վ",0x14EC},
+ {"վ",0x14ED}, {"Տ",0x14EE}, {"տ",0x14EF}, {"Ր",0x14F0}, {"ր",0x14F1}, {"Ց",0x14F2}, {"ց",0x14F3},
+ {"Ւ",0x14F4}, {"ւ",0x14F5}, {"Փ",0x14F6}, {"փ",0x14F7}, {"Ք",0x14F8}, {"ք",0x14F9}, {"Օ",0x14FA},
+ {"օ",0x14FB}, {"Ֆ",0x14FC}, {"ֆ",0x14FD}, {"՚",0x14FE}, {"§",0x14FF}, {"ა",0x15D0}, {"ბ",0x15D1},
+ {"გ",0x15D2}, {"დ",0x15D3}, {"ე",0x15D4}, {"ვ",0x15D5}, {"ზ",0x15D6}, {"თ",0x15D7}, {"ი",0x15D8},
+ {"კ",0x15D9}, {"ლ",0x15DA}, {"მ",0x15DB}, {"ნ",0x15DC}, {"ო",0x15DD}, {"პ",0x15DE}, {"ჟ",0x15DF},
+ {"რ",0x15E0}, {"ს",0x15E1}, {"ტ",0x15E2}, {"უ",0x15E3}, {"ფ",0x15E4}, {"ქ",0x15E5}, {"ღ",0x15E6},
+ {"ყ",0x15E7}, {"შ",0x15E8}, {"ჩ",0x15E9}, {"ც",0x15EA}, {"ძ",0x15EB}, {"წ",0x15EC}, {"ჭ",0x15ED},
+ {"ხ",0x15EE}, {"ჯ",0x15EF}, {"ჰ",0x15F0}, {"ჱ",0x15F1}, {"ჲ",0x15F2}, {"ჳ",0x15F3}, {"ჴ",0x15F4},
+ {"ჵ",0x15F5}, {"ჶ",0x15F6}, {"Ẋ",0x16A3}, {"Ĭ",0x16A6}, {"Ƶ",0x16A9}, {"Ǧ",0x16AA}, {"Ɵ",0x16AF},
+ {"ẋ",0x16B3}, {"ĭ",0x16B6}, {"ƶ",0x16B9}, {"ǧ",0x16BA}, {"ǒ",0x16BD}, {"ɵ",0x16BF}, {"Ə",0x16C6},
+ {"Ḷ",0x16D1}, {"ḷ",0x16E1}, {"ə",0x16F6}, {"̃",0x1E9F}, {"Ạ",0x1EA0}, {"ạ",0x1EA1}, {"Ả",0x1EA2},
+ {"ả",0x1EA3}, {"Ấ",0x1EA4}, {"ấ",0x1EA5}, {"Ầ",0x1EA6}, {"ầ",0x1EA7}, {"Ẩ",0x1EA8}, {"ẩ",0x1EA9},
+ {"Ẫ",0x1EAA}, {"ẫ",0x1EAB}, {"Ậ",0x1EAC}, {"ậ",0x1EAD}, {"Ắ",0x1EAE}, {"ắ",0x1EAF}, {"Ằ",0x1EB0},
+ {"ằ",0x1EB1}, {"Ẳ",0x1EB2}, {"ẳ",0x1EB3}, {"Ẵ",0x1EB4}, {"ẵ",0x1EB5}, {"Ặ",0x1EB6}, {"ặ",0x1EB7},
+ {"Ẹ",0x1EB8}, {"ẹ",0x1EB9}, {"Ẻ",0x1EBA}, {"ẻ",0x1EBB}, {"Ẽ",0x1EBC}, {"ẽ",0x1EBD}, {"Ế",0x1EBE},
+ {"ế",0x1EBF}, {"Ề",0x1EC0}, {"ề",0x1EC1}, {"Ể",0x1EC2}, {"ể",0x1EC3}, {"Ễ",0x1EC4}, {"ễ",0x1EC5},
+ {"Ệ",0x1EC6}, {"ệ",0x1EC7}, {"Ỉ",0x1EC8}, {"ỉ",0x1EC9}, {"Ị",0x1ECA}, {"ị",0x1ECB}, {"Ọ",0x1ECC},
+ {"ọ",0x1ECD}, {"Ỏ",0x1ECE}, {"ỏ",0x1ECF}, {"Ố",0x1ED0}, {"ố",0x1ED1}, {"Ồ",0x1ED2}, {"ồ",0x1ED3},
+ {"Ổ",0x1ED4}, {"ổ",0x1ED5}, {"Ỗ",0x1ED6}, {"ỗ",0x1ED7}, {"Ộ",0x1ED8}, {"ộ",0x1ED9}, {"Ớ",0x1EDA},
+ {"ớ",0x1EDB}, {"Ờ",0x1EDC}, {"ờ",0x1EDD}, {"Ở",0x1EDE}, {"ở",0x1EDF}, {"Ỡ",0x1EE0}, {"ỡ",0x1EE1},
+ {"Ợ",0x1EE2}, {"ợ",0x1EE3}, {"Ụ",0x1EE4}, {"ụ",0x1EE5}, {"Ủ",0x1EE6}, {"ủ",0x1EE7}, {"Ứ",0x1EE8},
+ {"ứ",0x1EE9}, {"Ừ",0x1EEA}, {"ừ",0x1EEB}, {"Ử",0x1EEC}, {"ử",0x1EED}, {"Ữ",0x1EEE}, {"ữ",0x1EEF},
+ {"Ự",0x1EF0}, {"ự",0x1EF1}, {"̀",0x1EF2}, {"́",0x1EF3}, {"Ỵ",0x1EF4}, {"ỵ",0x1EF5}, {"Ỷ",0x1EF6},
+ {"ỷ",0x1EF7}, {"Ỹ",0x1EF8}, {"ỹ",0x1EF9}, {"Ơ",0x1EFA}, {"ơ",0x1EFB}, {"Ư",0x1EFC}, {"ư",0x1EFD},
+ {"̉",0x1EFE}, {"̣",0x1EFF}, {"₠",0x20A0}, {"₡",0x20A1}, {"₢",0x20A2}, {"₣",0x20A3}, {"₤",0x20A4},
+ {"₥",0x20A5}, {"₦",0x20A6}, {"₧",0x20A7}, {"₨",0x20A8}, {"₩",0x20A9}, {"₪",0x20AA}, {"₫",0x20AB},
+ {"€",0x20AC},
+ {"~",0xFF5E},
+};
+
+static const std::map<QString, quint32> xKeyCodes {
+ {"Return", XK_Return}, {"BackSpace", XK_BackSpace}, {"Ctrl", XK_Control_L},
+ {"Win", XK_Super_L}, {"Tab", XK_Tab}, {"Alt", XK_Alt_L}, {"Esc", XK_Escape},
+ {"Shift", XK_Shift_L}, {"Menu", XK_Menu}, {"Insert", XK_Insert},
+ {"Home", XK_Home}, {"End", XK_End}, {"Space", XK_space}, {" ", XK_space},
+
+ {"VolumeUp", XF86XK_AudioRaiseVolume}, {"VolumeDown", XF86XK_AudioLowerVolume}, {"VolumeMute", XF86XK_AudioMute},
+ {"PauseSong", XF86XK_AudioPause}, {"NextSong", XF86XK_AudioNext}, {"PrevSong", XF86XK_AudioPrev},
+
+ {"BrightnessUp", XF86XK_KbdBrightnessUp}, {"BrightnessDown", XF86XK_KbdBrightnessDown},
+
+ {"Left", XK_Left}, {"Right", XK_Right}, {"Up", XK_Up}, {"Down", XK_Down},
+ {"PgU", XK_Page_Up}, {"PgD", XK_Page_Down},
+
+ {"F1", XK_F1}, {"F2", XK_F2}, {"F3", XK_F3}, {"F4", XK_F4}, {"F5", XK_F5}, {"F6", XK_F6},
+ {"F7", XK_F7}, {"F8", XK_F8}, {"F9", XK_F9}, {"F10", XK_F10}, {"F11", XK_F11}, {"F12", XK_F12},
+
+ {"0", XK_0}, {"1", XK_1}, {"2", XK_2}, {"3", XK_3}, {"4", XK_4}, {"5", XK_5},
+ {"6", XK_6}, {"7", XK_7}, {"8", XK_8}, {"9", XK_9},
+
+ {"A", XK_A}, {"B", XK_B}, {"C", XK_C}, {"D", XK_D}, {"E", XK_E}, {"F", XK_F},
+ {"G", XK_G}, {"H", XK_H}, {"I", XK_I}, {"J", XK_J}, {"K", XK_K}, {"L", XK_L},
+ {"M", XK_M}, {"N", XK_N}, {"O", XK_O}, {"P", XK_P}, {"Q", XK_Q}, {"R", XK_R},
+ {"S", XK_S}, {"T", XK_T}, {"U", XK_U}, {"V", XK_V}, {"W", XK_W}, {"X", XK_X},
+ {"Y", XK_Y}, {"Z", XK_Z},
+
+ {"a", XK_a}, {"b", XK_b}, {"c", XK_c}, {"d", XK_d}, {"e", XK_e}, {"f", XK_f},
+ {"g", XK_g}, {"h", XK_h}, {"i", XK_i}, {"j", XK_j}, {"k", XK_k}, {"l", XK_l},
+ {"m", XK_m}, {"n", XK_n}, {"o", XK_o}, {"p", XK_p}, {"q", XK_q}, {"r", XK_r},
+ {"s", XK_s}, {"t", XK_t}, {"u", XK_u}, {"v", XK_v}, {"w", XK_w}, {"x", XK_x},
+ {"y", XK_y}, {"z", XK_z}, {"§",0x00A7},
+
+ {"\\", XK_backslash}, {"'", XK_apostrophe}, {",", XK_comma}, {"-", XK_minus},
+ {".", XK_period}, {"/", XK_slash}, {";", XK_semicolon}, {"=", XK_equal},
+ {"[", XK_bracketleft}, {"]", XK_bracketright}, /*{"`", XK_grave},*/
+ {"<", XK_less},
+};
+
+static const std::map<QString, quint32> xUpKeyCodes {
+ {"!", XK_exclam}, {"\"", XK_quotedbl}, {"#", XK_numbersign}, {"$", XK_dollar},
+ {"%", XK_percent}, {"&", XK_ampersand}, {"(", XK_parenleft},
+ {")", XK_parenright}, {"*", XK_asterisk}, {"+", XK_plus},
+ {":", XK_colon}, {">", XK_greater}, {"~", XK_asciitilde},
+ {"?", XK_question}, {"@", XK_at}, {"^", XK_asciicircum}, {"_", XK_underscore},
+ {":-D", 0},
+};
+
+static const QList<Qt::Key> qtKeyCodes {
+ {Qt::Key_Backspace, Qt:: Key_Enter, Qt::Key_Return, Qt::Key_Plus,
+ Qt::Key_Slash, Qt::Key_AsciiCircum, Qt::Key_AsciiTilde, Qt::Key_Equal
+ }
+};
+static const QList<Qt::Key> qtKeyCodes2 {
+ // √ € ™ “
+ {Qt::Key(8730), Qt::Key(8364), Qt::Key(8482), Qt::Key(8220),
+ // ” … ~ ?
+ Qt::Key(8221), Qt::Key(8230), Qt::Key(65374), Qt::Key(65311),
+ // ! ; :
+ Qt::Key(65281), Qt::Key(65307), Qt::Key(65306),
+ }
+};
diff --git a/tests/manual/x11vkbwrapper/main.cpp b/tests/manual/x11vkbwrapper/main.cpp
new file mode 100644
index 00000000..cb8a25dc
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/main.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** 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 <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QDBusConnection>
+#include <QtVirtualKeyboard>
+#include <QObject>
+#include <QtDBus/QtDBus>
+#include <X11/Xutil.h>
+
+#include <atspi/atspi.h>
+#include <dbus/dbus.h>
+
+#include "handlekeyevents.h"
+#include "handleatspievents.h"
+#include "handledbusforchrome.h"
+#include "common_defs.h"
+
+#ifdef QT_TESTING_RUN
+ #include "handlelanguagechange.h"
+#endif
+
+int main(int argc, char *argv[])
+{
+ qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
+
+ bool error = false;
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
+ QGuiApplication app(argc, argv);
+
+ /** Setup DBus starts */
+ auto *extensionHandler = new HandleDbusForChrome(&app);
+ if (!QDBusConnection::sessionBus().isConnected()) {
+ qWarning() << "Cannot connect to the D-Bus session bus.\n"
+ << "To start it, run:\n"
+ << "\teval `dbus-launch --auto-syntax`\n";
+ }
+
+ QDBusConnection::sessionBus().registerObject("/", &app);
+ if (!QDBusConnection::sessionBus().registerService(SERVICE_NAME))
+ {
+ qWarning() << "Failed to register D-Bus service x11vkb.chromium.dbus.service: " << qPrintable(QDBusConnection::sessionBus().lastError().message());
+ }
+ /** Setup DBus ends */
+
+ QQmlApplicationEngine engine(QStringLiteral("qrc:/main.qml"));
+ engine.load(QStringLiteral("qrc:/keyboard.qml"));
+
+ QQmlContext* ctx = engine.rootContext();
+
+ /** Only for testing purpose*/
+ #ifdef QT_TESTING_RUN
+ ctx->setContextProperty("QT_TESTING_RUN", QVariant(true));
+ #endif
+
+ HandleKeyEvents handleKeyEvents;
+ if (!handleKeyEvents.init()) {
+ qWarning() << "Creation of xdo_t instance failed";
+ error = true;
+ }
+ app.installEventFilter(&handleKeyEvents);
+ ctx->setContextProperty("receiver", &handleKeyEvents);
+
+ HandleATSPIEvents handleATSPIEvents;
+ if (!handleATSPIEvents.init()) {
+ error = true;
+ }
+ ctx->setContextProperty("atspiFocus", &handleATSPIEvents);
+
+ QObject *switchObject = engine.rootObjects().first();
+ QObject *keyboardObject = engine.rootObjects().last();
+ QScreen *screen = app.primaryScreen();
+ QRect screenRect = screen->geometry();
+ int x1 = 0;
+ int y1 = 0;
+ int x2 = 0;
+ int y2 = 0;
+ screenRect.getCoords(&x1, &y1, &x2, &y2);
+
+ switchObject->setProperty("x", x2 - switchObject->property("width").toInt());
+ switchObject->setProperty("y", y2 - switchObject->property("height").toInt());
+ keyboardObject->setProperty("x", x2 - static_cast<int>(screen->size().rwidth()/keyboardObject->property("scaleFactor").toFloat()));
+ keyboardObject->setProperty("y", y2 - switchObject->property("height").toInt());
+
+ QObject::connect(extensionHandler, &HandleDbusForChrome::showKeyboard, &handleATSPIEvents, &HandleATSPIEvents::setKeyboardVisible);
+
+ /** Only for testing purpose*/
+ #ifdef QT_TESTING_RUN
+ HandleLanguageChange hj;
+ QObject::connect(engine.rootObjects().last(), SIGNAL(languageChangedSignal(QString)),
+ &hj, SLOT(languageChanged(QString)));
+ #endif
+
+ /** If error(s) exit */
+ if (!error) {
+ return app.exec();
+ } else {
+ return 1;
+ }
+}
diff --git a/tests/manual/x11vkbwrapper/main.qml b/tests/manual/x11vkbwrapper/main.qml
new file mode 100644
index 00000000..fb5e4dc8
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/main.qml
@@ -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$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Window 2.2
+
+
+Window {
+ id: window
+ width: d.vkbSwitchSize
+ height: d.vkbSwitchSize
+ color: "transparent"
+ visible: !Qt.inputMethod.visible
+ flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.FramelessWindowHint
+
+ QtObject {
+ id: d
+ readonly property int vkbSwitchSize: 30
+ }
+
+ Image {
+ id: qtLogo
+ anchors.fill: parent
+ source: "graphics/Qt_logo.png"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ atspiFocus.setKeyboardVisible(!Qt.inputMethod.visible)
+ }
+ }
+ }
+}
+
diff --git a/tests/manual/x11vkbwrapper/qml.qrc b/tests/manual/x11vkbwrapper/qml.qrc
new file mode 100644
index 00000000..519156ab
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/qml.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>graphics/Qt_logo.png</file>
+ <file>keyboard.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/x11vkbwrapper/vkbhidetimer.cpp b/tests/manual/x11vkbwrapper/vkbhidetimer.cpp
new file mode 100644
index 00000000..25e52e5e
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbhidetimer.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 "vkbhidetimer.h"
+#include <QGuiApplication>
+#include <QTimer>
+#include <QGlobalStatic>
+
+namespace {
+const quint16 KvkbCloseTimeout= 5000;
+}
+
+Q_GLOBAL_STATIC(CloseTimer,uniqueInstance)
+
+VkbHideTimer::VkbHideTimer(QObject *parent) : QObject(parent)
+{
+ m_vkbHideTimer = new QTimer(this);
+ m_vkbHideTimer->setInterval(KvkbCloseTimeout);
+ m_vkbHideTimer->setSingleShot(true);
+ QObject::connect(m_vkbHideTimer, &QTimer::timeout, this, &VkbHideTimer::closeVKB);
+}
+
+VkbHideTimer::~VkbHideTimer() {
+
+}
+
+VkbHideTimer* VkbHideTimer::getInstance() {
+ return uniqueInstance;
+}
+
+void VkbHideTimer::startTimer() {
+ m_vkbHideTimer->start();
+}
+
+void VkbHideTimer::closeVKB() const {
+ QGuiApplication::inputMethod()->hide();
+}
diff --git a/tests/manual/x11vkbwrapper/vkbhidetimer.h b/tests/manual/x11vkbwrapper/vkbhidetimer.h
new file mode 100644
index 00000000..a4f3e223
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbhidetimer.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 VKBHIDETIMER_H
+#define VKBHIDETIMER_H
+
+#include <QObject>
+
+class QTimer;
+
+class VkbHideTimer : public QObject
+{
+ Q_OBJECT
+ friend class CloseTimer;
+public:
+ static VkbHideTimer *getInstance();
+ virtual ~VkbHideTimer();
+
+private:
+ explicit VkbHideTimer(QObject *parent = nullptr);
+ VkbHideTimer( const VkbHideTimer& ) = delete;
+ VkbHideTimer& operator=( const VkbHideTimer& ) = delete;
+
+public:
+ void startTimer();
+
+private slots:
+ void closeVKB() const;
+
+private:
+ QTimer *m_vkbHideTimer;
+};
+
+class CloseTimer : public VkbHideTimer
+{
+};
+#endif // VKBHIDETIMER_H
diff --git a/tests/manual/x11vkbwrapper/vkbnativehost/common_defs.h b/tests/manual/x11vkbwrapper/vkbnativehost/common_defs.h
new file mode 100644
index 00000000..b4d92ce7
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbnativehost/common_defs.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** 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 COMMONDEFS_H
+#define COMMONDEFS_H
+
+#define SERVICE_NAME "x11vkb.chromium.dbus.service"
+
+#endif // COMMONDEFS_H
diff --git a/tests/manual/x11vkbwrapper/vkbnativehost/install_host.sh b/tests/manual/x11vkbwrapper/vkbnativehost/install_host.sh
new file mode 100755
index 00000000..8eae33d1
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbnativehost/install_host.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+#******************************************************************************
+#**
+#** 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$
+#**
+#****************************************************************************/
+
+set -e
+BROWSER=$1
+HOST_PATH=$2
+HOST_APP_NAME=x11vkbnativehost
+HOST_JSON_NAME=x11vkb.host.json
+
+function echo_error_and_exit {
+ echo $1
+ echo "Use case: ./install_host.sh chromium [or chrome] /full/path/to/executable"
+ exit 1
+}
+
+if [ "$BROWSER" != "chromium" ] && [ "$BROWSER" != "chrome" ]; then
+ echo_error_and_exit "use chromium or chrome as the first parameter"
+fi
+
+if [ ! -f "$HOST_PATH/$HOST_APP_NAME" ]; then
+ if [ ! -f "$HOST_PATH" ]; then
+ echo_error_and_exit "executable at path $HOST_PATH not found"
+ else
+ if [ $HOST_APP_NAME == "${HOST_PATH##*/}" ]; then
+ HOST_PATH=$(echo $HOST_PATH | rev | cut -d'/' -f2- | rev)
+ else
+ echo_error_and_exit "executable at path $HOST_PATH/$HOST_APP_NAME not found"
+ fi
+ fi
+fi
+HOST_PATH=$(echo $HOST_PATH | sed 's:/*$::')
+
+DIR=$PWD
+
+if [ $BROWSER == "chromium" ]; then
+ TARGET_DIR="$HOME/.config/chromium/NativeMessagingHosts"
+else
+ TARGET_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"
+fi
+
+# Create directory to store native messaging host.
+mkdir -p "$TARGET_DIR"
+
+# Copy native messaging host manifest.
+cp "$DIR/$HOST_JSON_NAME" "$TARGET_DIR"
+
+# Update host path in the manifest.
+ESCAPED_HOST_PATH=${HOST_PATH////\\/}
+
+sed -i -e "s/HOST_PATH/$ESCAPED_HOST_PATH/" "$TARGET_DIR/$HOST_JSON_NAME"
+
+# Set permissions for the manifest so that all users can read it.
+chmod o+r "$TARGET_DIR/$HOST_JSON_NAME"
+
+echo $HOST_JSON_NAME has been installed.
diff --git a/tests/manual/x11vkbwrapper/vkbnativehost/main.cpp b/tests/manual/x11vkbwrapper/vkbnativehost/main.cpp
new file mode 100644
index 00000000..8b28b6e6
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbnativehost/main.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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 <QtCore/QCoreApplication>
+#include <QtDBus/QtDBus>
+
+#include "common_defs.h"
+#include "sendertodbus.h"
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+
+ if (!QDBusConnection::sessionBus().isConnected()) {
+ return 1;
+ }
+
+ SenderToDbus senderToDbus;
+
+ app.exec();
+}
diff --git a/tests/manual/x11vkbwrapper/vkbnativehost/sendertodbus.cpp b/tests/manual/x11vkbwrapper/vkbnativehost/sendertodbus.cpp
new file mode 100644
index 00000000..a4e59453
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbnativehost/sendertodbus.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 <QtCore/QFile>
+#include <QtDBus/QtDBus>
+
+#include "sendertodbus.h"
+#include "common_defs.h"
+
+namespace {
+//!
+//! \brief msgLengthBytes, Chromium sends first 4 bytes as a length of coming message
+//!
+const qint8 msgLengthBytes = 4;
+
+//!
+//! \brief msgLength, Chromium sends next 1 byte as a true/false to popup/hide virtual keyboard
+//!
+const qint8 msgLength = 1;
+}
+
+
+
+SenderToDbus::SenderToDbus(QObject *parent)
+ : QObject(parent),
+ m_iface(nullptr)
+{
+ m_iface = new QDBusInterface(SERVICE_NAME, "/", "",
+ QDBusConnection::sessionBus(), this);
+ if (!m_iface->isValid()) {
+ QCoreApplication::quit();
+ }
+
+ this->forwardMessages();
+}
+
+void SenderToDbus::forwardMessages()
+{
+ m_qstdin.open(stdin, QIODevice::ReadOnly);
+
+ while (true)
+ {
+ // Read the message length (first 4 bytes)
+ QByteArray byteCount = m_qstdin.read(msgLengthBytes);
+
+ //When Chromium closes stdin is closed
+ if (byteCount.count() == 0)
+ {
+ // before exit, send false to hide keyboard
+ m_iface->setProperty("focusValue", false);
+ this->quit();
+ return;
+ }
+
+ QByteArray value = m_qstdin.read(msgLength);
+ m_iface->setProperty("focusValue", value == "1");
+ };
+}
+
+
+void SenderToDbus::quit()
+{
+ QTimer::singleShot(0, QCoreApplication::instance(), &QCoreApplication::quit);
+}
diff --git a/tests/manual/x11vkbwrapper/vkbnativehost/sendertodbus.h b/tests/manual/x11vkbwrapper/vkbnativehost/sendertodbus.h
new file mode 100644
index 00000000..39429569
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbnativehost/sendertodbus.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 SENDERTODBUS_H
+#define SENDERTODBUS_H
+
+#include <QtCore/QObject>
+#include <QtCore/QFile>
+#include <QtDBus/QDBusInterface>
+
+class SenderToDbus: public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit SenderToDbus(QObject *parent = nullptr);
+
+private:
+ //!
+ //! \brief forwardMessages
+ //! reads stdin where Chromium sends messages
+ //! and forwards them to dbus by setting value
+ //!
+ void forwardMessages();
+
+ //!
+ //! \brief quit
+ //! sets singleShot of timer
+ //! when the application is going to quit
+ //!
+ Q_NOREPLY void quit();
+
+private:
+ QFile m_qstdin;
+ QDBusInterface *m_iface;
+};
+
+#endif // SENDERTODBUS_H
diff --git a/tests/manual/x11vkbwrapper/vkbnativehost/vkbnativehost.pro b/tests/manual/x11vkbwrapper/vkbnativehost/vkbnativehost.pro
new file mode 100644
index 00000000..492d8273
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbnativehost/vkbnativehost.pro
@@ -0,0 +1,26 @@
+TARGET = x11vkbnativehost
+
+QT -= gui
+QT += dbus
+
+CONFIG += c++11 console
+CONFIG -= app_bundle
+
+# 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
+
+HEADERS += \
+ common_defs.h \
+ sendertodbus.h
+
+SOURCES += \
+ main.cpp \
+ sendertodbus.cpp
+
+DISTFILES += \
+ install_host.sh \
+ x11vkb.host.json
+
diff --git a/tests/manual/x11vkbwrapper/vkbnativehost/x11vkb.host.json b/tests/manual/x11vkbwrapper/vkbnativehost/x11vkb.host.json
new file mode 100644
index 00000000..b00ba287
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/vkbnativehost/x11vkb.host.json
@@ -0,0 +1,9 @@
+{
+ "name": "x11vkb.host",
+ "description": "Qt Virtual Keyboard Host",
+ "path": "HOST_PATH/x11vkbnativehost",
+ "type": "stdio",
+ "allowed_origins": [
+ "chrome-extension://ibmhlnijonocbgabbjfkdbegceoihcbp/"
+ ]
+}
diff --git a/tests/manual/x11vkbwrapper/x11vkbwrapper.pro b/tests/manual/x11vkbwrapper/x11vkbwrapper.pro
new file mode 100644
index 00000000..bb954c80
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/x11vkbwrapper.pro
@@ -0,0 +1,54 @@
+TEMPLATE = app
+TARGET = x11vkbwrapper
+
+QT += qml quick dbus virtualkeyboard svg
+CONFIG += c++11
+
+static {
+ QT += svg
+ QTPLUGIN += qtvirtualkeyboardplugin
+}
+
+# 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). Refer to the documentation for the
+# deprecated API to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# Uncomment below line and re-build before running tests.
+# Enables writing of the current selected language to a json file for the test application to pick up.
+#DEFINES += QT_TESTING_RUN
+
+##### Skip Debug prints if Release build
+CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT
+
+SOURCES += \
+ handlelanguagechange.cpp \
+ main.cpp \
+ handlekeyevents.cpp \
+ handleatspievents.cpp \
+ handledbusforchrome.cpp \
+ vkbhidetimer.cpp
+
+HEADERS += \
+ handlekeyevents.h \
+ handleatspievents.h \
+ handledbusforchrome.h \
+ common_defs.h \
+ handlelanguagechange.h \
+ keysymmapsforfakeinput.h \
+ vkbhidetimer.h \
+ xcbkeyboard.h
+
+RESOURCES += qml.qrc
+
+OTHER_FILES += main.qml
+
+INCLUDEPATH += /usr/include/X11
+INCLUDEPATH += /usr/include/at-spi-2.0
+INCLUDEPATH += /usr/lib/x86_64-linux-gnu/glib-2.0/include
+INCLUDEPATH += /usr/include/glib-2.0
+INCLUDEPATH += /usr/include/dbus-1.0
+INCLUDEPATH += /usr/lib/x86_64-linux-gnu/dbus-1.0/include
+
+LIBS += -lXtst -lX11 -latspi -lxdo
diff --git a/tests/manual/x11vkbwrapper/xcbkeyboard.h b/tests/manual/x11vkbwrapper/xcbkeyboard.h
new file mode 100644
index 00000000..56e45b97
--- /dev/null
+++ b/tests/manual/x11vkbwrapper/xcbkeyboard.h
@@ -0,0 +1,604 @@
+/****************************************************************************
+**
+** 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 XCBKEYBOARD_H
+#define XCBKEYBOARD_H
+// Following definitions and table are taken from
+// "qt5/qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp".
+
+#include <Qt>
+#include <X11/keysym.h>
+
+#ifndef XK_ISO_Left_Tab
+#define XK_ISO_Left_Tab 0xFE20
+#endif
+
+#ifndef XK_dead_hook
+#define XK_dead_hook 0xFE61
+#endif
+
+#ifndef XK_dead_horn
+#define XK_dead_horn 0xFE62
+#endif
+
+#ifndef XK_Codeinput
+#define XK_Codeinput 0xFF37
+#endif
+
+#ifndef XK_Kanji_Bangou
+#define XK_Kanji_Bangou 0xFF37 /* same as codeinput */
+#endif
+
+// Fix old X libraries
+#ifndef XK_KP_Home
+#define XK_KP_Home 0xFF95
+#endif
+#ifndef XK_KP_Left
+#define XK_KP_Left 0xFF96
+#endif
+#ifndef XK_KP_Up
+#define XK_KP_Up 0xFF97
+#endif
+#ifndef XK_KP_Right
+#define XK_KP_Right 0xFF98
+#endif
+#ifndef XK_KP_Down
+#define XK_KP_Down 0xFF99
+#endif
+#ifndef XK_KP_Prior
+#define XK_KP_Prior 0xFF9A
+#endif
+#ifndef XK_KP_Next
+#define XK_KP_Next 0xFF9B
+#endif
+#ifndef XK_KP_End
+#define XK_KP_End 0xFF9C
+#endif
+#ifndef XK_KP_Insert
+#define XK_KP_Insert 0xFF9E
+#endif
+#ifndef XK_KP_Delete
+#define XK_KP_Delete 0xFF9F
+#endif
+
+// the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special
+// multimedia keys. They are included here as not every system has them.
+#define XF86XK_MonBrightnessUp 0x1008FF02
+#define XF86XK_MonBrightnessDown 0x1008FF03
+#define XF86XK_KbdLightOnOff 0x1008FF04
+#define XF86XK_KbdBrightnessUp 0x1008FF05
+#define XF86XK_KbdBrightnessDown 0x1008FF06
+#define XF86XK_Standby 0x1008FF10
+#define XF86XK_AudioLowerVolume 0x1008FF11
+#define XF86XK_AudioMute 0x1008FF12
+#define XF86XK_AudioRaiseVolume 0x1008FF13
+#define XF86XK_AudioPlay 0x1008FF14
+#define XF86XK_AudioStop 0x1008FF15
+#define XF86XK_AudioPrev 0x1008FF16
+#define XF86XK_AudioNext 0x1008FF17
+#define XF86XK_HomePage 0x1008FF18
+#define XF86XK_Mail 0x1008FF19
+#define XF86XK_Start 0x1008FF1A
+#define XF86XK_Search 0x1008FF1B
+#define XF86XK_AudioRecord 0x1008FF1C
+#define XF86XK_Calculator 0x1008FF1D
+#define XF86XK_Memo 0x1008FF1E
+#define XF86XK_ToDoList 0x1008FF1F
+#define XF86XK_Calendar 0x1008FF20
+#define XF86XK_PowerDown 0x1008FF21
+#define XF86XK_ContrastAdjust 0x1008FF22
+#define XF86XK_Back 0x1008FF26
+#define XF86XK_Forward 0x1008FF27
+#define XF86XK_Stop 0x1008FF28
+#define XF86XK_Refresh 0x1008FF29
+#define XF86XK_PowerOff 0x1008FF2A
+#define XF86XK_WakeUp 0x1008FF2B
+#define XF86XK_Eject 0x1008FF2C
+#define XF86XK_ScreenSaver 0x1008FF2D
+#define XF86XK_WWW 0x1008FF2E
+#define XF86XK_Sleep 0x1008FF2F
+#define XF86XK_Favorites 0x1008FF30
+#define XF86XK_AudioPause 0x1008FF31
+#define XF86XK_AudioMedia 0x1008FF32
+#define XF86XK_MyComputer 0x1008FF33
+#define XF86XK_LightBulb 0x1008FF35
+#define XF86XK_Shop 0x1008FF36
+#define XF86XK_History 0x1008FF37
+#define XF86XK_OpenURL 0x1008FF38
+#define XF86XK_AddFavorite 0x1008FF39
+#define XF86XK_HotLinks 0x1008FF3A
+#define XF86XK_BrightnessAdjust 0x1008FF3B
+#define XF86XK_Finance 0x1008FF3C
+#define XF86XK_Community 0x1008FF3D
+#define XF86XK_AudioRewind 0x1008FF3E
+#define XF86XK_BackForward 0x1008FF3F
+#define XF86XK_Launch0 0x1008FF40
+#define XF86XK_Launch1 0x1008FF41
+#define XF86XK_Launch2 0x1008FF42
+#define XF86XK_Launch3 0x1008FF43
+#define XF86XK_Launch4 0x1008FF44
+#define XF86XK_Launch5 0x1008FF45
+#define XF86XK_Launch6 0x1008FF46
+#define XF86XK_Launch7 0x1008FF47
+#define XF86XK_Launch8 0x1008FF48
+#define XF86XK_Launch9 0x1008FF49
+#define XF86XK_LaunchA 0x1008FF4A
+#define XF86XK_LaunchB 0x1008FF4B
+#define XF86XK_LaunchC 0x1008FF4C
+#define XF86XK_LaunchD 0x1008FF4D
+#define XF86XK_LaunchE 0x1008FF4E
+#define XF86XK_LaunchF 0x1008FF4F
+#define XF86XK_ApplicationLeft 0x1008FF50
+#define XF86XK_ApplicationRight 0x1008FF51
+#define XF86XK_Book 0x1008FF52
+#define XF86XK_CD 0x1008FF53
+#define XF86XK_Calculater 0x1008FF54
+#define XF86XK_Clear 0x1008FF55
+#define XF86XK_ClearGrab 0x1008FE21
+#define XF86XK_Close 0x1008FF56
+#define XF86XK_Copy 0x1008FF57
+#define XF86XK_Cut 0x1008FF58
+#define XF86XK_Display 0x1008FF59
+#define XF86XK_DOS 0x1008FF5A
+#define XF86XK_Documents 0x1008FF5B
+#define XF86XK_Excel 0x1008FF5C
+#define XF86XK_Explorer 0x1008FF5D
+#define XF86XK_Game 0x1008FF5E
+#define XF86XK_Go 0x1008FF5F
+#define XF86XK_iTouch 0x1008FF60
+#define XF86XK_LogOff 0x1008FF61
+#define XF86XK_Market 0x1008FF62
+#define XF86XK_Meeting 0x1008FF63
+#define XF86XK_MenuKB 0x1008FF65
+#define XF86XK_MenuPB 0x1008FF66
+#define XF86XK_MySites 0x1008FF67
+#define XF86XK_New 0x1008FF68
+#define XF86XK_News 0x1008FF69
+#define XF86XK_OfficeHome 0x1008FF6A
+#define XF86XK_Open 0x1008FF6B
+#define XF86XK_Option 0x1008FF6C
+#define XF86XK_Paste 0x1008FF6D
+#define XF86XK_Phone 0x1008FF6E
+#define XF86XK_Reply 0x1008FF72
+#define XF86XK_Reload 0x1008FF73
+#define XF86XK_RotateWindows 0x1008FF74
+#define XF86XK_RotationPB 0x1008FF75
+#define XF86XK_RotationKB 0x1008FF76
+#define XF86XK_Save 0x1008FF77
+#define XF86XK_Send 0x1008FF7B
+#define XF86XK_Spell 0x1008FF7C
+#define XF86XK_SplitScreen 0x1008FF7D
+#define XF86XK_Support 0x1008FF7E
+#define XF86XK_TaskPane 0x1008FF7F
+#define XF86XK_Terminal 0x1008FF80
+#define XF86XK_Tools 0x1008FF81
+#define XF86XK_Travel 0x1008FF82
+#define XF86XK_Video 0x1008FF87
+#define XF86XK_Word 0x1008FF89
+#define XF86XK_Xfer 0x1008FF8A
+#define XF86XK_ZoomIn 0x1008FF8B
+#define XF86XK_ZoomOut 0x1008FF8C
+#define XF86XK_Away 0x1008FF8D
+#define XF86XK_Messenger 0x1008FF8E
+#define XF86XK_WebCam 0x1008FF8F
+#define XF86XK_MailForward 0x1008FF90
+#define XF86XK_Pictures 0x1008FF91
+#define XF86XK_Music 0x1008FF92
+#define XF86XK_Battery 0x1008FF93
+#define XF86XK_Bluetooth 0x1008FF94
+#define XF86XK_WLAN 0x1008FF95
+#define XF86XK_UWB 0x1008FF96
+#define XF86XK_AudioForward 0x1008FF97
+#define XF86XK_AudioRepeat 0x1008FF98
+#define XF86XK_AudioRandomPlay 0x1008FF99
+#define XF86XK_Subtitle 0x1008FF9A
+#define XF86XK_AudioCycleTrack 0x1008FF9B
+#define XF86XK_Time 0x1008FF9F
+#define XF86XK_Select 0x1008FFA0
+#define XF86XK_View 0x1008FFA1
+#define XF86XK_TopMenu 0x1008FFA2
+#define XF86XK_Red 0x1008FFA3
+#define XF86XK_Green 0x1008FFA4
+#define XF86XK_Yellow 0x1008FFA5
+#define XF86XK_Blue 0x1008FFA6
+#define XF86XK_Suspend 0x1008FFA7
+#define XF86XK_Hibernate 0x1008FFA8
+#define XF86XK_TouchpadToggle 0x1008FFA9
+#define XF86XK_TouchpadOn 0x1008FFB0
+#define XF86XK_TouchpadOff 0x1008FFB1
+#define XF86XK_AudioMicMute 0x1008FFB2
+
+
+// end of XF86keysyms.h
+
+// keyboard mapping table
+static const unsigned int KeyTbl[] = {
+
+ // misc keys
+
+ XK_Escape, Qt::Key_Escape,
+ XK_Tab, Qt::Key_Tab,
+ XK_ISO_Left_Tab, Qt::Key_Backtab,
+ XK_BackSpace, Qt::Key_Backspace,
+ XK_Return, Qt::Key_Return,
+ XK_Insert, Qt::Key_Insert,
+ XK_Delete, Qt::Key_Delete,
+ XK_Clear, Qt::Key_Delete,
+ XK_Pause, Qt::Key_Pause,
+ XK_Print, Qt::Key_Print,
+ 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq
+ 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq
+
+ /*
+ * Latin 1
+ * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)
+ * Byte 3 = 0
+ */
+
+ // XK_section, Qt::Key_section,
+ XK_guillemotleft, Qt::Key_guillemotleft,
+ XK_guillemotright, Qt::Key_guillemotright,
+
+ // cursor movement
+
+ XK_Home, Qt::Key_Home,
+ XK_End, Qt::Key_End,
+ XK_Left, Qt::Key_Left,
+ XK_Up, Qt::Key_Up,
+ XK_Right, Qt::Key_Right,
+ XK_Down, Qt::Key_Down,
+ XK_Prior, Qt::Key_PageUp,
+ XK_Next, Qt::Key_PageDown,
+
+ // modifiers
+
+ XK_Shift_L, Qt::Key_Shift,
+ XK_Shift_R, Qt::Key_Shift,
+ XK_Shift_Lock, Qt::Key_Shift,
+ XK_Control_L, Qt::Key_Control,
+ XK_Control_R, Qt::Key_Control,
+ XK_Meta_L, Qt::Key_Meta,
+ XK_Meta_R, Qt::Key_Meta,
+ XK_Alt_L, Qt::Key_Alt,
+ XK_Alt_R, Qt::Key_Alt,
+ XK_Caps_Lock, Qt::Key_CapsLock,
+ XK_Num_Lock, Qt::Key_NumLock,
+ XK_Scroll_Lock, Qt::Key_ScrollLock,
+ XK_Super_L, Qt::Key_Super_L,
+ XK_Super_R, Qt::Key_Super_R,
+ XK_Menu, Qt::Key_Menu,
+ XK_Hyper_L, Qt::Key_Hyper_L,
+ XK_Hyper_R, Qt::Key_Hyper_R,
+ XK_Help, Qt::Key_Help,
+ 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab
+ 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11)
+ 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12)
+
+ // numeric and function keypad keys
+
+ XK_KP_Space, Qt::Key_Space,
+ XK_KP_Tab, Qt::Key_Tab,
+ XK_KP_Enter, Qt::Key_Enter,
+ //XK_KP_F1, Qt::Key_F1,
+ //XK_KP_F2, Qt::Key_F2,
+ //XK_KP_F3, Qt::Key_F3,
+ //XK_KP_F4, Qt::Key_F4,
+ XK_KP_Home, Qt::Key_Home,
+ XK_KP_Left, Qt::Key_Left,
+ XK_KP_Up, Qt::Key_Up,
+ XK_KP_Right, Qt::Key_Right,
+ XK_KP_Down, Qt::Key_Down,
+ XK_KP_Prior, Qt::Key_PageUp,
+ XK_KP_Next, Qt::Key_PageDown,
+ XK_KP_End, Qt::Key_End,
+ XK_KP_Begin, Qt::Key_Clear,
+ XK_KP_Insert, Qt::Key_Insert,
+ XK_KP_Delete, Qt::Key_Delete,
+ XK_KP_Equal, Qt::Key_Equal,
+ XK_KP_Multiply, Qt::Key_Asterisk,
+ XK_KP_Add, Qt::Key_Plus,
+ XK_KP_Separator, Qt::Key_Comma,
+ XK_KP_Subtract, Qt::Key_Minus,
+ XK_KP_Decimal, Qt::Key_Period,
+ XK_KP_Divide, Qt::Key_Slash,
+
+
+ // special non-XF86 function keys
+
+ XK_Undo, Qt::Key_Undo,
+ XK_Redo, Qt::Key_Redo,
+ XK_Find, Qt::Key_Find,
+ XK_Cancel, Qt::Key_Cancel,
+
+ // International input method support keys
+
+ // International & multi-key character composition
+ XK_ISO_Level3_Shift, Qt::Key_AltGr,
+ XK_Multi_key, Qt::Key_Multi_key,
+ XK_Codeinput, Qt::Key_Codeinput,
+ XK_SingleCandidate, Qt::Key_SingleCandidate,
+ XK_MultipleCandidate, Qt::Key_MultipleCandidate,
+ XK_PreviousCandidate, Qt::Key_PreviousCandidate,
+
+ // Misc Functions
+ XK_Mode_switch, Qt::Key_Mode_switch,
+ XK_script_switch, Qt::Key_Mode_switch,
+
+ // Japanese keyboard support
+ XK_Kanji, Qt::Key_Kanji,
+ XK_Muhenkan, Qt::Key_Muhenkan,
+ //XK_Henkan_Mode, Qt::Key_Henkan_Mode,
+ XK_Henkan_Mode, Qt::Key_Henkan,
+ XK_Henkan, Qt::Key_Henkan,
+ XK_Romaji, Qt::Key_Romaji,
+ XK_Hiragana, Qt::Key_Hiragana,
+ XK_Katakana, Qt::Key_Katakana,
+ XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana,
+ XK_Zenkaku, Qt::Key_Zenkaku,
+ XK_Hankaku, Qt::Key_Hankaku,
+ XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku,
+ XK_Touroku, Qt::Key_Touroku,
+ XK_Massyo, Qt::Key_Massyo,
+ XK_Kana_Lock, Qt::Key_Kana_Lock,
+ XK_Kana_Shift, Qt::Key_Kana_Shift,
+ XK_Eisu_Shift, Qt::Key_Eisu_Shift,
+ XK_Eisu_toggle, Qt::Key_Eisu_toggle,
+ //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou,
+ //XK_Zen_Koho, Qt::Key_Zen_Koho,
+ //XK_Mae_Koho, Qt::Key_Mae_Koho,
+ XK_Kanji_Bangou, Qt::Key_Codeinput,
+ XK_Zen_Koho, Qt::Key_MultipleCandidate,
+ XK_Mae_Koho, Qt::Key_PreviousCandidate,
+
+#ifdef XK_KOREAN
+ // Korean keyboard support
+ XK_Hangul, Qt::Key_Hangul,
+ XK_Hangul_Start, Qt::Key_Hangul_Start,
+ XK_Hangul_End, Qt::Key_Hangul_End,
+ XK_Hangul_Hanja, Qt::Key_Hangul_Hanja,
+ XK_Hangul_Jamo, Qt::Key_Hangul_Jamo,
+ XK_Hangul_Romaja, Qt::Key_Hangul_Romaja,
+ //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput,
+ XK_Hangul_Codeinput, Qt::Key_Codeinput,
+ XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja,
+ XK_Hangul_Banja, Qt::Key_Hangul_Banja,
+ XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja,
+ XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja,
+ //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate,
+ //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate,
+ //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate,
+ XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate,
+ XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate,
+ XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate,
+ XK_Hangul_Special, Qt::Key_Hangul_Special,
+ //XK_Hangul_switch, Qt::Key_Hangul_switch,
+ XK_Hangul_switch, Qt::Key_Mode_switch,
+#endif // XK_KOREAN
+
+ // dead keys
+ XK_dead_grave, Qt::Key_Dead_Grave,
+ XK_dead_acute, Qt::Key_Dead_Acute,
+ XK_dead_circumflex, Qt::Key_Dead_Circumflex,
+ XK_dead_tilde, Qt::Key_Dead_Tilde,
+ XK_dead_macron, Qt::Key_Dead_Macron,
+ XK_dead_breve, Qt::Key_Dead_Breve,
+ XK_dead_abovedot, Qt::Key_Dead_Abovedot,
+ XK_dead_diaeresis, Qt::Key_Dead_Diaeresis,
+ XK_dead_abovering, Qt::Key_Dead_Abovering,
+ XK_dead_doubleacute, Qt::Key_Dead_Doubleacute,
+ XK_dead_caron, Qt::Key_Dead_Caron,
+ XK_dead_cedilla, Qt::Key_Dead_Cedilla,
+ XK_dead_ogonek, Qt::Key_Dead_Ogonek,
+ XK_dead_iota, Qt::Key_Dead_Iota,
+ XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound,
+ XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound,
+ XK_dead_belowdot, Qt::Key_Dead_Belowdot,
+ XK_dead_hook, Qt::Key_Dead_Hook,
+ XK_dead_horn, Qt::Key_Dead_Horn,
+ XK_dead_stroke, Qt::Key_Dead_Stroke,
+ XK_dead_abovecomma, Qt::Key_Dead_Abovecomma,
+ XK_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma,
+ XK_dead_doublegrave, Qt::Key_Dead_Doublegrave,
+ XK_dead_belowring, Qt::Key_Dead_Belowring,
+ XK_dead_belowmacron, Qt::Key_Dead_Belowmacron,
+ XK_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex,
+ XK_dead_belowtilde, Qt::Key_Dead_Belowtilde,
+ XK_dead_belowbreve, Qt::Key_Dead_Belowbreve,
+ XK_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis,
+ XK_dead_invertedbreve, Qt::Key_Dead_Invertedbreve,
+ XK_dead_belowcomma, Qt::Key_Dead_Belowcomma,
+ XK_dead_currency, Qt::Key_Dead_Currency,
+ XK_dead_a, Qt::Key_Dead_a,
+ XK_dead_A, Qt::Key_Dead_A,
+ XK_dead_e, Qt::Key_Dead_e,
+ XK_dead_E, Qt::Key_Dead_E,
+ XK_dead_i, Qt::Key_Dead_i,
+ XK_dead_I, Qt::Key_Dead_I,
+ XK_dead_o, Qt::Key_Dead_o,
+ XK_dead_O, Qt::Key_Dead_O,
+ XK_dead_u, Qt::Key_Dead_u,
+ XK_dead_U, Qt::Key_Dead_U,
+ XK_dead_small_schwa, Qt::Key_Dead_Small_Schwa,
+ XK_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa,
+ XK_dead_greek, Qt::Key_Dead_Greek,
+ XK_dead_lowline, Qt::Key_Dead_Lowline,
+ XK_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline,
+ XK_dead_belowverticalline, Qt::Key_Dead_Belowverticalline,
+ XK_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay,
+
+ // Special keys from X.org - This include multimedia keys,
+ // wireless/bluetooth/uwb keys, special launcher keys, etc.
+ XF86XK_Back, Qt::Key_Back,
+ XF86XK_Forward, Qt::Key_Forward,
+ XF86XK_Stop, Qt::Key_Stop,
+ XF86XK_Refresh, Qt::Key_Refresh,
+ XF86XK_Favorites, Qt::Key_Favorites,
+ XF86XK_AudioMedia, Qt::Key_LaunchMedia,
+ XF86XK_OpenURL, Qt::Key_OpenUrl,
+ XF86XK_HomePage, Qt::Key_HomePage,
+ XF86XK_Search, Qt::Key_Search,
+ XF86XK_AudioLowerVolume, Qt::Key_VolumeDown,
+ XF86XK_AudioMute, Qt::Key_VolumeMute,
+ XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp,
+ XF86XK_AudioPlay, Qt::Key_MediaPlay,
+ XF86XK_AudioStop, Qt::Key_MediaStop,
+ XF86XK_AudioPrev, Qt::Key_MediaPrevious,
+ XF86XK_AudioNext, Qt::Key_MediaNext,
+ XF86XK_AudioRecord, Qt::Key_MediaRecord,
+ XF86XK_AudioPause, Qt::Key_MediaPause,
+ XF86XK_Mail, Qt::Key_LaunchMail,
+ XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 6: remap properly
+ XF86XK_Calculator, Qt::Key_Launch1,
+ XF86XK_Memo, Qt::Key_Memo,
+ XF86XK_ToDoList, Qt::Key_ToDoList,
+ XF86XK_Calendar, Qt::Key_Calendar,
+ XF86XK_PowerDown, Qt::Key_PowerDown,
+ XF86XK_ContrastAdjust, Qt::Key_ContrastAdjust,
+ XF86XK_Standby, Qt::Key_Standby,
+ XF86XK_MonBrightnessUp, Qt::Key_MonBrightnessUp,
+ XF86XK_MonBrightnessDown, Qt::Key_MonBrightnessDown,
+ XF86XK_KbdLightOnOff, Qt::Key_KeyboardLightOnOff,
+ XF86XK_KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp,
+ XF86XK_KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown,
+ XF86XK_PowerOff, Qt::Key_PowerOff,
+ XF86XK_WakeUp, Qt::Key_WakeUp,
+ XF86XK_Eject, Qt::Key_Eject,
+ XF86XK_ScreenSaver, Qt::Key_ScreenSaver,
+ XF86XK_WWW, Qt::Key_WWW,
+ XF86XK_Sleep, Qt::Key_Sleep,
+ XF86XK_LightBulb, Qt::Key_LightBulb,
+ XF86XK_Shop, Qt::Key_Shop,
+ XF86XK_History, Qt::Key_History,
+ XF86XK_AddFavorite, Qt::Key_AddFavorite,
+ XF86XK_HotLinks, Qt::Key_HotLinks,
+ XF86XK_BrightnessAdjust, Qt::Key_BrightnessAdjust,
+ XF86XK_Finance, Qt::Key_Finance,
+ XF86XK_Community, Qt::Key_Community,
+ XF86XK_AudioRewind, Qt::Key_AudioRewind,
+ XF86XK_BackForward, Qt::Key_BackForward,
+ XF86XK_ApplicationLeft, Qt::Key_ApplicationLeft,
+ XF86XK_ApplicationRight, Qt::Key_ApplicationRight,
+ XF86XK_Book, Qt::Key_Book,
+ XF86XK_CD, Qt::Key_CD,
+ XF86XK_Calculater, Qt::Key_Calculator,
+ XF86XK_Clear, Qt::Key_Clear,
+ XF86XK_ClearGrab, Qt::Key_ClearGrab,
+ XF86XK_Close, Qt::Key_Close,
+ XF86XK_Copy, Qt::Key_Copy,
+ XF86XK_Cut, Qt::Key_Cut,
+ XF86XK_Display, Qt::Key_Display,
+ XF86XK_DOS, Qt::Key_DOS,
+ XF86XK_Documents, Qt::Key_Documents,
+ XF86XK_Excel, Qt::Key_Excel,
+ XF86XK_Explorer, Qt::Key_Explorer,
+ XF86XK_Game, Qt::Key_Game,
+ XF86XK_Go, Qt::Key_Go,
+ XF86XK_iTouch, Qt::Key_iTouch,
+ XF86XK_LogOff, Qt::Key_LogOff,
+ XF86XK_Market, Qt::Key_Market,
+ XF86XK_Meeting, Qt::Key_Meeting,
+ XF86XK_MenuKB, Qt::Key_MenuKB,
+ XF86XK_MenuPB, Qt::Key_MenuPB,
+ XF86XK_MySites, Qt::Key_MySites,
+ XF86XK_New, Qt::Key_New,
+ XF86XK_News, Qt::Key_News,
+ XF86XK_OfficeHome, Qt::Key_OfficeHome,
+ XF86XK_Open, Qt::Key_Open,
+ XF86XK_Option, Qt::Key_Option,
+ XF86XK_Paste, Qt::Key_Paste,
+ XF86XK_Phone, Qt::Key_Phone,
+ XF86XK_Reply, Qt::Key_Reply,
+ XF86XK_Reload, Qt::Key_Reload,
+ XF86XK_RotateWindows, Qt::Key_RotateWindows,
+ XF86XK_RotationPB, Qt::Key_RotationPB,
+ XF86XK_RotationKB, Qt::Key_RotationKB,
+ XF86XK_Save, Qt::Key_Save,
+ XF86XK_Send, Qt::Key_Send,
+ XF86XK_Spell, Qt::Key_Spell,
+ XF86XK_SplitScreen, Qt::Key_SplitScreen,
+ XF86XK_Support, Qt::Key_Support,
+ XF86XK_TaskPane, Qt::Key_TaskPane,
+ XF86XK_Terminal, Qt::Key_Terminal,
+ XF86XK_Tools, Qt::Key_Tools,
+ XF86XK_Travel, Qt::Key_Travel,
+ XF86XK_Video, Qt::Key_Video,
+ XF86XK_Word, Qt::Key_Word,
+ XF86XK_Xfer, Qt::Key_Xfer,
+ XF86XK_ZoomIn, Qt::Key_ZoomIn,
+ XF86XK_ZoomOut, Qt::Key_ZoomOut,
+ XF86XK_Away, Qt::Key_Away,
+ XF86XK_Messenger, Qt::Key_Messenger,
+ XF86XK_WebCam, Qt::Key_WebCam,
+ XF86XK_MailForward, Qt::Key_MailForward,
+ XF86XK_Pictures, Qt::Key_Pictures,
+ XF86XK_Music, Qt::Key_Music,
+ XF86XK_Battery, Qt::Key_Battery,
+ XF86XK_Bluetooth, Qt::Key_Bluetooth,
+ XF86XK_WLAN, Qt::Key_WLAN,
+ XF86XK_UWB, Qt::Key_UWB,
+ XF86XK_AudioForward, Qt::Key_AudioForward,
+ XF86XK_AudioRepeat, Qt::Key_AudioRepeat,
+ XF86XK_AudioRandomPlay, Qt::Key_AudioRandomPlay,
+ XF86XK_Subtitle, Qt::Key_Subtitle,
+ XF86XK_AudioCycleTrack, Qt::Key_AudioCycleTrack,
+ XF86XK_Time, Qt::Key_Time,
+ XF86XK_Select, Qt::Key_Select,
+ XF86XK_View, Qt::Key_View,
+ XF86XK_TopMenu, Qt::Key_TopMenu,
+ XF86XK_Red, Qt::Key_Red,
+ XF86XK_Green, Qt::Key_Green,
+ XF86XK_Yellow, Qt::Key_Yellow,
+ XF86XK_Blue, Qt::Key_Blue,
+ XF86XK_Bluetooth, Qt::Key_Bluetooth,
+ XF86XK_Suspend, Qt::Key_Suspend,
+ XF86XK_Hibernate, Qt::Key_Hibernate,
+ XF86XK_TouchpadToggle, Qt::Key_TouchpadToggle,
+ XF86XK_TouchpadOn, Qt::Key_TouchpadOn,
+ XF86XK_TouchpadOff, Qt::Key_TouchpadOff,
+ XF86XK_AudioMicMute, Qt::Key_MicMute,
+ XF86XK_Launch0, Qt::Key_Launch2, // ### Qt 6: remap properly
+ XF86XK_Launch1, Qt::Key_Launch3,
+ XF86XK_Launch2, Qt::Key_Launch4,
+ XF86XK_Launch3, Qt::Key_Launch5,
+ XF86XK_Launch4, Qt::Key_Launch6,
+ XF86XK_Launch5, Qt::Key_Launch7,
+ XF86XK_Launch6, Qt::Key_Launch8,
+ XF86XK_Launch7, Qt::Key_Launch9,
+ XF86XK_Launch8, Qt::Key_LaunchA,
+ XF86XK_Launch9, Qt::Key_LaunchB,
+ XF86XK_LaunchA, Qt::Key_LaunchC,
+ XF86XK_LaunchB, Qt::Key_LaunchD,
+ XF86XK_LaunchC, Qt::Key_LaunchE,
+ XF86XK_LaunchD, Qt::Key_LaunchF,
+ XF86XK_LaunchE, Qt::Key_LaunchG,
+ XF86XK_LaunchF, Qt::Key_LaunchH,
+
+ 0, 0
+};
+#endif // XCBKEYBOARD_H