Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QtVirtualKeyboard freezes QML application with platform WebGL, but desktop works fine. How to unfreeze it or work around it?

The long version

I am running a QML application in the browser using WebGL as a platform. Everything is working fine until I try to integrate the QtVirtualKeyboard to fill in some textfields and editable ComboBox'es. When running the project in the browser, the first message received is:

This plugin does not support dynamic OpenGL loading!

This error message/warning is not linked to the VirtualKeyboard (VK) though, I suspect, as removing all traces of the VK does not make the message disappear. A screenshot of the browser window can be viewed below.

The application running in the browser

The next message occurs on clicking the text input field:

This plugin does not support setting window masks

Half the screen stays black - this is the area where on a refresh the VK will be located. Again - screenshot below.

Browser after interaction with the textfield - the lower half is blackened out where the virtual keyboard is located

After refreshing, three more messages appear. I will leave out the first two as they are basically saying "You pressed the Alt key and the F5 key". The third message is:

requestActivate() called for  QtVirtualKeyboard::InputView(0x4a16590)  which has Qt::WindowDoesNotAcceptFocus set.

Now the keyboad is visible, but every time a key is struck on the VK, new messages appear, while no text is written to the textfield:

This plugin does not support setting window masks
This plugin does not support setting window masks
qt.virtualkeyboard: InputContext::sendKeyClick(): no focus to send key click - QGuiApplication::focusWindow() is: QtVirtualKeyboard::InputView(0x4a16590)
This plugin does not support setting window masks

In addition to this, input from my keyboard seems to be ignored once the project is in this state. A hard reset (shutting down the program and restarting) restores functionality up to the VK being called, refreshing the page does not trigger any text to appear in the textfield. The final view that I got is shown below:

The keyboad is shown where previously, darkness blocked half the screen. This is the final state of the program until it is shut down.

I have created a minimal example which should demonstrate the problem. It is a slightly modified empty QML project as created by Qt Creator 4.13.2.

Running it on Desktop should work, the problematic behavior occurs if the project receives the command line arguments -platform webgl:port=80. I am using MSVC2019 32bit and Qt 5.15.1. The problem was reproducible in Microsoft Edge 44.18362.387.0 and Firefox 68.5.0esr (32 bit).

Chrome Version 86.0.4240.111 (64 bit) was a bit different, though: while inputs where not shown directly, refreshing the webpage entered the content afterwards. Minimizing the keyboard doesn't work, though, so this is no solution.

# TestVirtualKeyboard.pro (autogenerated by QtCreator)
QT += quick virtualkeyboard

CONFIG += c++11

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
  qputenv("QSG_RENDER_LOOP", "threaded"); // Addendum for Windows, does not change the problematic behavior
  qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));

  QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

  QGuiApplication app(argc, argv);

  QQmlApplicationEngine engine;
  const QUrl url(QStringLiteral("qrc:/main.qml"));
  QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                   &app, [url](QObject *obj, const QUrl &objUrl) {
    if (!obj && url == objUrl)
      QCoreApplication::exit(-1);
  }, Qt::QueuedConnection);
  engine.load(url);

  return app.exec();
}

// main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.VirtualKeyboard 2.15
import QtQuick.Controls 2.5

Window {
    id: window
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    color: "grey"

    TextInput {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: parent.top
        width: 320
        height: 30

        Rectangle {
            anchors.centerIn: parent
            width: parent.width + 4
            height: parent.height + 4
            color: "white"
            border.color: "black"
            border.width: 1
            radius: 2
            z: -1
        }
    }
}

TL,DR: QtVirtualKeyboard works if run in Desktop application but freezes the application if the platform is WebGL and an editable text element is selected.

Question: Is there a way to get QtVirtualKeyboard to run in Qt/WebGL applications or is there another way/tool that can be used to get keyboard capabilities with Qt/WebGL applications on Touch devices? Bonus points for not having to write my own keyboard element.

What I have tried so far:

  • I searched some popular search engines but came up short.
  • Multiple browsers, with no satisfactory success.
  • Some issues were found that are Unity-related, which would be a crosspost to another forum. These seem not to apply to my problem, as I suspect that Qt/QML/WebGL and Unity/WebGL will be vastly different and I have no experience with Unity.
  • I am uncertain as to how this question is related: QT WebGL-stream, virtualKeyboard and touch screen problem
like image 531
Alexander Mayer Avatar asked Oct 29 '20 11:10

Alexander Mayer


1 Answers

With the help of Qt Support, I got it working. The way I did it, calling the Qt Virtual Keyboard results in the application trying to make the keyboard a top level window on top of the application. This is how the Desktop case is treated as well, but there it works.

To avoid this behavior, one has to embed the keyboard into the QML window. For this to happen, an InputPanel can be added to the QML window like so:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.VirtualKeyboard 2.15
import QtQuick.Controls 2.5

Window {
    id: window
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    color: "grey"

    TextInput {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: parent.top
        width: 320
        height: 30

        Rectangle {
            anchors.centerIn: parent
            width: parent.width + 4
            height: parent.height + 4
            color: "white"
            border.color: "black"
            border.width: 1
            radius: 2
            z: -1
        }
    }

    InputPanel {
        width: window.width
        y: window.height - height
        visible: active
    }
}

This did the trick for me.

like image 150
Alexander Mayer Avatar answered Oct 11 '22 18:10

Alexander Mayer