Skip to content

Qt for WebAssembly

Specific issues when using Qt for WebAssembly

437 Topics 1.7k Posts
  • 0 Votes
    5 Posts
    244 Views
    8Observer88

    The bug report was closed because You need to handle this in a javascript mouse event and not a Qt mouse event. I will continue here: https://forum.qt.io/topic/157373/emscripten_set_mousedown_callback-does-not-call-the-callback-function

  • 0 Votes
    6 Posts
    266 Views
    8Observer88

    Lorn Potter added a comment in the bug report

    The mouse cursor is owned by the browser, and apparently setting mouse position in the browser is not allowed due to security issues.

    I will continue to find another way to lock a mouse cursor in the following topic: emscripten_request_pointerlock() returns EMSCRIPTEN_RESULT_UNKNOWN_TARGET

  • 1 Votes
    3 Posts
    1k Views
    8Observer88

    pro:

    wasm: INCLUDEPATH += "C:\emsdk\upstream\emscripten\cache\sysroot\include"

    Settings for Qt 6.6.3:

    image.png

  • Unable to open WebSocket with a request parameter

    Unsolved
    5
    0 Votes
    5 Posts
    365 Views
    8Observer88

    I had a problem with connection with the server on the free Glitch hosting from WASM. I solved it by setting User-Agent. I use Qt 6.6.3. Maybe it will help:

    QUrl url("wss://merciful-regal-soursop.glitch.me"); QNetworkRequest request; request.setUrl(url); request.setRawHeader(QByteArray("User-Agent"), QByteArray("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36")); m_webSocket.open(request);

    And I had another problem with connection from Android. I was solved it like this: Get data with Qt client from deployed Node.js server using WebSockets

  • Detecting a mobile browser with Qt WebAssembly

    Solved
    4
    0 Votes
    4 Posts
    317 Views
    8Observer88

    I have replaced the follwing line in the code example above:

    #ifdef Q_OS_ANDROID

    with this one to detect iOS too:

    #if defined Q_OS_ANDROID || defined Q_OS_IOS
  • emscripten.h: No such file or directory

    Solved
    3
    0 Votes
    3 Posts
    268 Views
    8Observer88

    Solution is to add the following INCLUDEPATH:

    QT += core gui widgets INCLUDEPATH += "C:\emsdk\upstream\emscripten\cache\sysroot\include" CONFIG += c++17 SOURCES += \ main.cpp

    To avoid conflicting declaration do not compile for Desktop. Compile for WebAssembly.

  • Using IndexedDB in QWebAssembly

    Solved
    1
    0 Votes
    1 Posts
    94 Views
    No one has replied
  • 0 Votes
    5 Posts
    305 Views
    O

    This worked for me:

    QMAKE_LFLAGS += -Wl,-error-limit=0
  • run Qt WASM across private network

    Unsolved
    3
    0 Votes
    3 Posts
    362 Views
    B

    Hello @jhayar,

    It seems like you're facing issues with accessing a Qt application running as WebAssembly (WASM) from other devices within the same private network.

    Ensure your Qt application is configured to listen on localhost (127.0.0.1) and try accessing it from another device using the host machine's IP address instead of localhost. Double-check your network configuration to ensure that devices within the same subnet can communicate. If your Qt application is served through a web server like Nginx or Apache, ensure that CORS headers are correctly set to allow access from other IP addresses within your private network. Although HTTPS is recommended for security, if it's not feasible for your private setup, consider alternatives like configuring your network or application to allow HTTP connections securely within your private environment.

  • 0 Votes
    4 Posts
    1k Views
    S

    @semlanik said in configuring QT with webassembly issue: failed on Qt6ProtobufTools, WrapProtoc not found:

    -skip qtgrpc also can help in this case, if you don't need it in your Qt build.

    Yep - or uninstall Qt Protobuf component using the maintaince tool.

  • how to enable JSPI to use QSettings::WebIndexedDBFormat

    Unsolved
    4
    0 Votes
    4 Posts
    247 Views
    L

    @jsulm Thank you for your answer. I forgot to mention it. In fact, my chrome has enabled JSPI, but the error is as mentioned above...

  • 3D With Web Assembly

    Unsolved
    4
    0 Votes
    4 Posts
    603 Views
    lorn.potterL

    Probably not, as Qt3D makes liberal use of threads, and webassmbly (WebGL) only works in the main thread (WebWorker)

  • 1 Votes
    3 Posts
    230 Views
    S

    With normal caveats regarding "threads" (web workers in web parlance) you could just run your data simulation in a thread and then use the main thread to update your VBO and render.

  • Qt Creator runs WebAssembly in Internet Explorer

    Solved
    3
    0 Votes
    3 Posts
    256 Views
    8Observer88

    It works now on Chrome. I just have restarted Qt Creator.

  • How to include 3rd party library

    Unsolved
    6
    0 Votes
    6 Posts
    431 Views
    8Observer88

    @Saju I didn't use OpenCV. But try these steps that I use for another libraries:

    Add C:\emsdk\upstream\emscripten to the Path variable cd opencv-1.2.3 && mkdir build && cd build emcmake cmake .. emmake make INCLUDEPATH += "E:/libs/opencv-1.2.3/include" LIBS += -L"E:/libs/opencv-1.2.3/build/lib" LIBS += -lopencv
  • Problem using QFileDialog::saveFileContent on Chrome

    Unsolved
    3
    0 Votes
    3 Posts
    360 Views
    R

    Hello, @ryan1969.

    The problem was the saveFileContent function was being called at the end of a procedure that took a long time. I guess the browser could not link the function with the click event as you said. So I had to add another button for the user to click when the procedure finishes. This made everything work OK.

    Thank you for the help.

  • Qt6.7 Drag and Drop on WebAssembly

    Unsolved
    7
    0 Votes
    7 Posts
    445 Views
    JonBJ

    @PEPSoares said in Qt6.7 Drag and Drop on WebAssembly:

    QFile cannot open the file because the file does not exist....

    That does not surprise me. One would assume that the file is clearly a temporary file, valid somehow during the drag & drop, then removed. That is why I asked only if you could access the directory, not the file.

    Btw: QDir can access "/qt/tmp"

    The question was for //qt/tmp, not /qt/tmp.

  • How to use fileDialog with QML for Web Assembly

    Unsolved
    5
    0 Votes
    5 Posts
    679 Views
    J

    @Gilboonet it's been a while since you've asked the question, but as I found it then I'll just reply for future generations :)

    Basically you can't directly access any files on your devices from WASM. You need to use Browser API to achieve this, so the only option is to call native browser file picker for open & browser download for saving. You can pick which file to open, but when you save, then it's gonna be downloaded by a browser like any other file from a web (yes, it'll be saved in Downloads folder).

    It seems that Qt also supports file picking on WASM but unfortunately I didn't have a chance to test it yet: https://doc.qt.io/qt-6/qfiledialog.html#getOpenFileContent

    Here's a great example on how to use native file picker in Qt project:

    https://github.com/msorvig/qt-webassembly-examples/tree/master/gui_localfiles

    Here's my code, heavily based on above example, if you're interested:

    std::function<void(const QByteArray &, const QString &)> fileDataReadyCallback; extern "C" EMSCRIPTEN_KEEPALIVE void wasmFileDataReadyCallback(char *content, size_t contentSize, const char *fileName) { if (fileDataReadyCallback == nullptr) return; QByteArray data(content, contentSize); free(content); fileDataReadyCallback(data, QString::fromUtf8(fileName)); fileDataReadyCallback = nullptr; } void WasmPlatformIntegration::openFile() { openFile("*", [](const QByteArray &content, const QString &fileName) { qDebug() << "load file" << fileName << "size" << content.size(); }); } void WasmPlatformIntegration::openFile(const QString &fileNameFilter, std::function<void(const QByteArray &, const QString &)> fileDataReady) { if (::fileDataReadyCallback) puts("Warning: Concurrent loadFile() calls are not supported. Cancelling " "earlier call"); ::fileDataReadyCallback = nullptr; ::wasmFileDataReadyCallback(nullptr, 0, nullptr); ::fileDataReadyCallback = fileDataReady; EM_ASM_( { const fileNameFilter = UTF8ToString($0); // Crate file file input which whil display the native file dialog let fileElement = document.createElement("input"); document.body.appendChild(fileElement); fileElement.type = "file"; fileElement.style = "display:none"; fileElement.accept = fileNameFilter; fileElement.onchange = function(event) { const files = event.target.files; // Read files for (var i = 0; i < files.length; i++) { const file = files[i]; var reader = new FileReader(); reader.onload = function() { const name = file.name; let contentArray = new Uint8Array(reader.result); const contentSize = reader.result.byteLength; const heapPointer = _malloc(contentSize); const heapBytes = new Uint8Array(Module.HEAPU8.buffer, heapPointer, contentSize); heapBytes.set(contentArray); // Null out the first data copy to enable GC reader = null; contentArray = null; // Call the C++ file data ready callback ccall("wasmFileDataReadyCallback", null, [ "number", "number", "string" ], [ heapPointer, contentSize, name ]); }; reader.readAsArrayBuffer(file); } // Clean up document document.body.removeChild(fileElement); }; // onchange callback // Trigger file dialog open fileElement.click(); }, fileNameFilter.toUtf8().constData()); } void WasmPlatformIntegration::saveFile(const QByteArray &content, const QString &fileNameHint) { EM_ASM_( { const contentPointer = $0; const contentLength = $1; const fileNameHint = UTF8ToString($2); const fileContent = Module.HEAPU8.subarray(contentPointer, contentPointer + contentLength); const arrayBuffer = fileContent.slice(); const uint8Array = new Uint8Array(arrayBuffer); uint8Array.fill(255); const fileblob = new Blob([arrayBuffer]); // Create a hidden download link and click it programatically let link = document.createElement("a"); document.body.appendChild(link); link.download = fileNameHint; link.href = window.URL.createObjectURL(fileblob); link.style = "display:none"; link.click(); document.body.removeChild(link); }, content.constData(), content.size(), fileNameHint.toUtf8().constData()); }
  • QtLoader is deprecated in qt6.6.0

    Unsolved
    7
    0 Votes
    7 Posts
    1k Views
    E

    If you want to fetch your wasm file from a server using the new Qt 6.6 qt loader api you can do it like this:

    const wasmPromise = WebAssembly.compileStreaming(fetch(url)); const instance = await qtLoad({ qt: { onLoaded: () => { loadingScreen.style.display = "none"; }, onExit: exitData => { console.log(exitData); }, entryFunction: window.createQtAppInstance, containerElements: [mainScreen], module: wasmPromise, } });
  • RuntimeError: index out of bounds

    Unsolved
    2
    0 Votes
    2 Posts
    334 Views
    E

    First make sure you are compiling with the correct Emscripten version for the Qt version you are using. For Qt 6.5.2 it should be Emscripten 3.1.25. If that doesn't work add this line to your cmake file: target_link_options(PocketSolver PUBLIC -s STACK_SIZE=5MB), this should fix your error.