This is a text-only version of the following page on https://raymii.org:
---
Title : Expose any Qt5 program via VNC
Author : Remy van Elst
Date : 20-09-2021
URL : https://raymii.org/s/articles/Expose_any_QT_program_via_VNC.html
Format : Markdown/HTML
---
![Coffee Machine VNC][4]
> Remote Coffee Machine Qt GUI via VNC
A few months ago I wrote about [Microsoft Teams running on a coffee machine][1].
That was a fun work experiment where I got a VNC client running on the linux-based
coffee machines that we produce at work. In the [comments on hackernews][2] Jean-Michaël
Celerier pointed me to the reverse, a way to expose any Qt application over VNC.
This article shows you how I use this feature to work on our Qt 5 based coffee machine
frontend as well as how you can use this on your machine, for example, to expose Dolphin,
the KDE file manager, over VNC.
Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below:
I'm developing an open source monitoring app called Leaf Node Monitoring, for windows, linux & android. Go check it out!
Consider sponsoring me on Github. It means the world to me if you show your appreciation and you'll help pay the server costs.
You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $200 credit for 60 days. Spend $25 after your credit expires and I'll get $25!
Our Qt frontend for the coffee machines can run as a local application just fine, it's
nothing more than a client towards an HTTP API. One other such client is our
[touchless feature][5], that exposes a part of the machine over MQtT to a website.
One issue with running the Qt application on my workstation is that remote media
is not loaded. The coffee machine can display images and video (and show a QR code),
but those images are dynamically loaded in QML, via a filesystem path that my machine
does not have. I could setup an `sshfs` mount, but that would require fiddling with
permissions. In the instances that I have to work on that part of the code I run the
UI via VNC directly on a coffee machine, all the filesystem paths are available then.
### Qt 5 applications via VNC
You can append a command line flag to any Qt application or set an environment
variable to expose the application over VNC. The command line flag is
`-platform vnc` and the environment variable is `Qt_QPA_PLATFORM="vnc"`. Here
is how to run Dolphin via VNC on port 5900:
Qt_QPA_PLATFORM="vnc" dolphin
# or
dolphin -platform vnc
In the output you should see the following like:
QVncServer created on port 5900
The environment variable method is preferred as far as I can find online.
Use a VNC client to connect to `127.0.0.1:5900`, or if you have your firewall
disabled, you can connect from any other host on the network. Here is how
dolphin looks on my workstation, via VNC:
![dolphin vnc][6]
There is no window management and no title bar as you can see. There is also
no way to password protect the VNC service. The colours might be a bit off
since the colour depth via VNC can be different than your own screen.
The size of the VNC window can be controlled by appending `:size=WxH`, like so:
Qt_QPA_PLATFORM="vnc:size=1920x1280"
Here is `KDiamond`, a Bejeweled-type game running with a size parameter, you can see
that the scaling is a bit off:
kdiamond -platform vnc:size=300x400
Screenshot:
![kdiamond][11]
### Qt Platform Abstraction and other technical details
The VNC plugin is a [QPA (Qt Platform Abstraction)][7] plugin. QPA plugins are
responsible for the actual rendering of the Qt application, most often on
screen. There are plugins for Android, Windows, Linux (`xcb` being the default
for X11) and Wayland, but also for more exotic platforms like Haiku, WinRT or
Mir.
Our coffee machine UI uses the [EGLFS plugin][10] for hardware accelerated
graphical output without an X server. `EGLFS` is a platform plugin for running
Qt5 applications on top of EGL and OpenGL ES 2.0, without an actual windowing
system like X11 or Wayland. In addition to Qt Quick 2 and native OpenGL
applications, EGLFS supports software-rendered windows, like QWidget, too.
There is even a WebGL plugin, to stream an application directly to a website.
Couldn't get that to work, maybe an idea for a future article.
The VNC plugin is not documented well, but it was added in Qt 5.8. I found out
that it also supports a `port=` parameter by peeking into the [source code
for `QVncIntegration`][8]. I found [the `size=WxH` parameter][9] in the source as
well.
Your platform must have the library installed for it to work, but often it's
available with your distro's base Qt5 framework packages. My Arch Linux
install got it with the default KDE5 installation and on Ubuntu the plugin
file is provided by the package `libqt5gui5`, as the
[search on packages.ubuntu.com][3] shows:
/usr/lib/i386-linux-gnu/qt5/plugins/platforms/libqvnc.so libqt5gui5 [i386]
You can also query the available plugins on your system passing an invalid parameter
to the `-platform` flag:
dolphin -platform garbage
Output:
qt.qpa.plugin: Could not find the Qt platform plugin "garbage" in "" This
application failed to start because no Qt platform plugin could be
initialized. Reinstalling the application may fix this problem.
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl,
offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl,
wayland-xcomposite-glx, xcb.
Aborted (core dumped)
The core dump is rather sad, but you get the gist, This output is useful, instead of a
generic error message like `plugin not found`, help the user by listing the available
options. I often complain about Qt, but I have to give them this one, this error
message is helpful.
For reference, on my Arch Linux system the following plugins are available:
$ ls /usr/lib/qt/plugins/platforms
total 1.5M
drwxr-xr-x 2 root root 4.0K Sep 16 19:55 .
drwxr-xr-x 62 root root 12K Sep 16 19:56 ..
-rwxr-xr-x 1 root root 18K Sep 4 23:24 libqeglfs.so
-rwxr-xr-x 1 root root 466K Sep 4 23:24 libqlinuxfb.so
-rwxr-xr-x 1 root root 138K Sep 4 23:24 libqminimal.so
-rwxr-xr-x 1 root root 171K Sep 4 23:24 libqminimalegl.so
-rwxr-xr-x 1 root root 182K Sep 4 23:24 libqoffscreen.so
-rwxr-xr-x 1 root root 238K Sep 4 23:24 libqvnc.so
-rwxr-xr-x 1 root root 66K Sep 7 09:14 libqwayland-egl.so
-rwxr-xr-x 1 root root 18K Sep 7 09:14 libqwayland-generic.so
-rwxr-xr-x 1 root root 75K Sep 7 09:14 libqwayland-xcomposite-egl.so
-rwxr-xr-x 1 root root 54K Sep 7 09:14 libqwayland-xcomposite-glx.so
-rwxr-xr-x 1 root root 18K Sep 4 23:24 libqxcb.so
If you know a way to get the WebGL plugin working, please let me know! I'd love
to experiment with that, WebAssembly requires many changes to applications,
but WebGL should be as simple as the VNC plugin, just a variable or command line
argument.
[1]: /s/blog/MS_Teams_on_a_Coffee_Machine_or_Framebuffer_VNC_Client.html
[2]: https://news.ycombinator.com/item?id=26759988
[3]: http://web.archive.org/web/20210920170302/https://packages.ubuntu.com/search?searchon=contents&keywords=libqvnc.so&mode=exactfilename&suite=hirsute&arch=any
[4]: /s/inc/img/qt-vnc-1.png
[5]: /s/articles/Rectangle_debugging_in_QML_just_like_printf.html
[6]: /s/inc/img/qt-vnc-2.png
[7]: http://web.archive.org/web/20210920172207/https://doc.qt.io/qt-5/qpa.html
[8]: https://code.qt.io/cgit/qt/qtbase.git/tree/src/plugins/platforms/vnc/qvncintegration.cpp?h=dev
[9]: https://code.qt.io/cgit/qt/qtbase.git/tree/src/plugins/platforms/vnc/qvncscreen.cpp#n78
[10]: http://web.archive.org/web/20210920191005/https://doc.qt.io/qt-5/embedded-linux.html
[11]: /s/inc/img/qt-vnc-3.png
---
License:
All the text on this website is free as in freedom unless stated otherwise.
This means you can use it in any way you want, you can copy it, change it
the way you like and republish it, as long as you release the (modified)
content under the same license to give others the same freedoms you've got
and place my name and a link to this site with the article as source.
This site uses Google Analytics for statistics and Google Adwords for
advertisements. You are tracked and Google knows everything about you.
Use an adblocker like ublock-origin if you don't want it.
All the code on this website is licensed under the GNU GPL v3 license
unless already licensed under a license which does not allows this form
of licensing or if another license is stated on that page / in that software:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Just to be clear, the information on this website is for meant for educational
purposes and you use it at your own risk. I do not take responsibility if you
screw something up. Use common sense, do not 'rm -rf /' as root for example.
If you have any questions then do not hesitate to contact me.
See https://raymii.org/s/static/About.html for details.