aboutsummaryrefslogtreecommitdiffstats
path: root/tests/manual/x11vkbtest/mousesimulator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/x11vkbtest/mousesimulator.cpp')
-rw-r--r--tests/manual/x11vkbtest/mousesimulator.cpp367
1 files changed, 367 insertions, 0 deletions
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;
+}