Make Desktop Qt 5 application run with mir-kiosk on Ubuntu Core

I managed to build a snap of my Qt5/ QML user interface application which works on Ubuntu Desktop. I’m using the snapcraft-desktop-helpers according to these instructions. However, my goal is to run the user interface on Ubuntu Core connected to a touchscreen. I figured out that I need to use mir-kiosk and followed mainly Part 13 of the instructions.

However, I’m not sure how these two helpers are intended to work together - if at all. I’m assuming that the mir-kiosk-snap-launch is not configuring anything with the Qt5 dependencies. But on the other side the desktop-helpers are not setting anything with the wayland Mir interface.

Is mir-kiosk-snap-launch even intended to set the necessary Qt configurations/ paths? Or how should I proceed?

This is my snapcraft.yaml:

name: test
base: core18 
version: '0.2' 
summary: The Software 
description: |
  This snap includes the software to operate the high-level
  control PC.

grade: devel
confinement: devmode

apps:
  run:
    command: wayland-launch roslaunch nav_gui gui.launch

  run2:
    command: wayland-launch bin/desktop-launch roslaunch nav_gui gui.launch

  run3:
    command: bin/desktop-launch roslaunch nav_gui gui.launch

  run4:
    command: bin/desktop-launch wayland-launch roslaunch nav_gui gui.launch

  daemon:
    command: run-daemon wayland-launch roslaunch nav_gui gui.launch
    daemon: simple
    restart-condition: always

  rostopic:
    command: rostopic

  rosservice:
    command: rosservice

plugs:
  wayland:

parts: 

  desktop-qt5:
    source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
    source-subdir: qt
    plugin: make
    make-parameters: ["FLAVOR=qt5"]
    build-packages:
      - build-essential
      - qtbase5-dev
      - qt5-default
      - libqt5quick5
      - qtdeclarative5-dev
      - qtquickcontrols2-5-dev
      - qtmultimedia5-dev
      - dpkg-dev
    stage-packages:
      - libqt5qml5
      - libqt5quick5
      - libqt5quickcontrols2-5
      - libqt5quicktemplates2-5
      - qml-module-qtquick-layouts
      - qml-module-qtquick-controls
      - qml-module-qtquick-controls2
      - qml-module-qtmultimedia
      - qml-module-qtquick-extras
      - libxkbcommon0
      - ttf-ubuntu-font-family
      - dmz-cursor-theme
      - light-themes
      - adwaita-icon-theme
      - gnome-themes-standard
      - shared-mime-info
      - libqt5gui5
      - libgdk-pixbuf2.0-0
      - libqt5svg5 # for loading icon themes which are svg
      - try: [appmenu-qt5] # not available on core18
      - locales-all
      - xdg-user-dirs
      - fcitx-frontend-qt5

  workspace:
    plugin: catkin-tools
    source: .
    rosinstall-files: [snap/local/snap.rosinstall]
    recursive-rosinstall: true
    catkin-packages: [catkin_simple, nav_gui]
    build-packages: [git]
    after: [desktop-qt5]

  mir-kiosk-snap-launch:
    plugin: dump
    source: https://github.com/MirServer/mir-kiosk-snap-launch.git
    override-build:  $SNAPCRAFT_PART_BUILD/build-with-plugs.sh wayland

Reduced to the relevant parts of the errors, this is what I get in the different situations with this snapcraft.yaml:

  • bin/desktop-launch works on Ubuntu Desktop, but on Core for obvious reasons:
qt.qpa.screen: QXcbConnection: Could not connect to display 
Could not connect to any X display.
  • wayland-launch on Core:
+ [ ! -O /run/user/1000/wayland-0 ]
+ echo waiting for Wayland socket
waiting for Wayland socket
  • run-daemon wayland-launch on Core:
Jan 09 15:32:37 localhost test.daemon[10788]: This application failed to start because it could not find or load the Qt platform plugin "xcb"
Jan 09 15:32:37 localhost test.daemon[10788]: in "".
  • bin/desktop-launch wayland-launch on Core:
+ [ ! -O /run/user/1000/wayland-0 ]
+ echo waiting for Wayland socket
waiting for Wayland socket

Can you please point me in the right direction?

This is the tutorial I’m actually linking and following in my post.

Btw, running glmark2-wayland as shown in the example works fine.

The /run/user/1000/wayland-0 indicates you are not running the snap as a daemon as described in the tutorial.

That’s not going to work without a mir-kiosk running as the same user (which is tricky on Core).

What errors are shown by:

snap logs -n 100 test

I need to clarify: I was only running run-daemon wayland-launch roslaunch nav_gui gui.launch as a daemon, which resulted in:

This application failed to start because it could not find or load the Qt platform plugin "xcb" in "".

I had this error before, when I didn’t use the desktop-qt5 helpers. This is why I’m wondering how I include Qt5 correctly again, when using mir-kiosk-snap-launch.

The other commands are run1 to run4 from the snapcraft.yaml apps, which I executed “manually”. So I assume executing them manually is never a good idea.

OK. That problem is because Qt is trying to find the X11 backend and failing. You don’t want the X11 backend (which Qt calls “xcb”), you want the wayland backend.

Here’s an example that configures Qt to run as a kiosk:

1 Like

You could probably run them as root (i.e. with sudo).

Thanks, I will try this. Do I even need the desktop-qt5 from the desktop helpers or should I just copy the dependencies and leave the desktop-launch out?

In the end I just need it as a daemon. I thought it would simplify things when running it not as a daemon first (was reading this in another tutorial). But in this case, I will not do this anymore.

You probably don’t need desktop helpers to get Qt to work, it was developed to help with desktop integration and isn’t well adapted to non-desktop. Good luck!

1 Like

So thanks to your example application, I got my Qt user interface running without any problems. I tried to strip down the code as much as possible. But I still lack some understanding for the following things:

  1. From my last snapcraft.yaml, I have many Qt5 build- and stage-packages included. But in the example I just see 4 Qt-related stage-packages. I assume this is because the examples are already pre-built and that’s why I still need them, right?

  2. The snappy-qt5.conf file points to these stage- and build-packages, right?

  3. The text in my UI when built with snapcraft appears different than before. For example, it doesn’t fit on buttons anymore. Why is this?

  4. Before, we discussed about always using mir-kiosk apps as daemon. But in the example snapcraft.yaml, there is still this mir-kiosk-apps entry. Why?

  5. I don’t have anything about opengl or mesa in my snapcraft.yaml. Do I even need these?

Parts that stage packages installed from .debs automatically bring the corresponding dependencies into the snap.

That’s what it looks like, there are several ways to do this.

I don’t know. I suspect you may have picked up a style/theme from your desktop environment that affects typeface or size.

That isn’t required. It allows the snap to be run directly on the desktop, which is convenient for testing.

Yes, they are not provided by the core snap. But you may be getting them pulled into your snap by something else you stage, in which case you don’t need to mention them explicitly.

E.g.

$ apt depends qtwayland5
qtwayland5
  Depends: libc6 (>= 2.14)
  Depends: libegl1
  Depends: libgcc1 (>= 1:3.4)
  Depends: libgl1
  Depends: libqt5core5a (>= 5.9.5+dfsg~)
  Depends: libqt5gui5 (>= 5.9.5+dfsg~)
  Depends: libqt5waylandclient5 (>= 5.9.2)
  Depends: libqt5waylandcompositor5 (>= 5.9.0~rc)
  Depends: libstdc++6 (>= 5)
  Depends: libwayland-client0 (>= 1.9.91)
 |Depends: libwayland-egl1-mesa (>= 10.0.2)
  Depends: libwayland-egl1
  Depends: libwayland-server0 (>= 1.6.0)
  Depends: libx11-6
  Depends: libxcomposite1 (>= 1:0.3-1)
  Depends: <qtbase-abi-5-9-5>
    libqt5core5a
1 Like

I’m now getting another error which I can’t really decipher. Building and running the snap on my desktop system works without any problems. However, when I use my snapcraft.yaml for the Ubuntu Core mir-kiosk, I have problems running the daemon. In short, I get the error: RLException: cannot resolve host address for machine [localhost]. I tried to search for this, but can’t really associate the issue.

This is the log while trying to start the daemon and failing:

Mar 02 21:20:04 localhost systemd[1]: Started Service for snap application nav.daemon.
Mar 02 21:20:04 localhost nav.daemon[2979]: + grep -q snap_core= /proc/cmdline
Mar 02 21:20:04 localhost nav.daemon[2979]: + exec wayland-launch roslaunch nav_gui gui.launch
Mar 02 21:20:04 localhost nav.daemon[2979]: + mkdir -p /run/user/0/snap.nav -m 700
Mar 02 21:20:04 localhost nav.daemon[2979]: + [ -z  ]
Mar 02 21:20:04 localhost nav.daemon[2979]: + WAYLAND_DISPLAY=wayland-0
Mar 02 21:20:04 localhost nav.daemon[2979]: + dirname /run/user/0/snap.nav
Mar 02 21:20:04 localhost nav.daemon[2979]: + real_wayland=/run/user/0/wayland-0
Mar 02 21:20:04 localhost nav.daemon[2979]: + [ ! -O /run/user/0/wayland-0 ]
Mar 02 21:20:04 localhost nav.daemon[2979]: + ln -sf /run/user/0/wayland-0 /run/user/0/snap.nav
Mar 02 21:20:04 localhost nav.daemon[2979]: + unset DISPLAY
Mar 02 21:20:04 localhost nav.daemon[2979]: + exec roslaunch nav_gui gui.launch
Mar 02 21:20:04 localhost nav.daemon[2979]: RLException: cannot resolve host address for machine [localhost]
Mar 02 21:20:04 localhost nav.daemon[2979]: The traceback for the exception was written to the log file
Mar 02 21:20:04 localhost nav.daemon[2979]: ... logging to /root/snap/nav/x2/ros/log/33cefede-5cc3-11ea-9048-65db37667638/roslaunch-localhost-2979.log
Mar 02 21:20:04 localhost nav.daemon[2979]: Checking log directory for disk usage. This may take awhile.
Mar 02 21:20:04 localhost nav.daemon[2979]: Press Ctrl-C to interrupt
Mar 02 21:20:04 localhost nav.daemon[2979]: Done checking log file disk usage. Usage is <1GB.
Mar 02 21:20:04 localhost nav.daemon[2979]: [68B blob data]
Mar 02 21:20:05 localhost systemd[1]: snap.nav.daemon.service: Main process exited, code=exited, status=1/FAILURE
Mar 02 21:20:05 localhost systemd[1]: snap.nav.daemon.service: Failed with result 'exit-code'.
Mar 02 21:20:05 localhost systemd[1]: snap.nav.daemon.service: Service hold-off time over, scheduling restart.
Mar 02 21:20:05 localhost systemd[1]: snap.nav.daemon.service: Scheduled restart job, restart counter is at 1.
Mar 02 21:20:05 localhost systemd[1]: Stopped Service for snap application nav.daemon.

I assume that the snapcraft.yaml must cause this error, since the code builds and runs fine when not built with snapcraft. Any ideas?

Here is my latest snapcraft.yaml:

name: nav
base: core18 # the base snap is the execution environment for this snap
version: 'w1.0' # just for humans, typically '1.2+git' or '1.3.2'
summary: The Nav Software # 79 char long summary
description: |
  This snap includes the software to operate Nav from the high-level
  control PC.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

apps: # apps are commands and services exposed to end users

  daemon:
    command: run-daemon wayland-launch roslaunch nav_gui gui.launch
    daemon: simple
    restart-condition: always

  rostopic:
    command: rostopic

  rosservice:
    command: rosservice

plugs:
  opengl:
  wayland:

environment:
  __EGL_VENDOR_LIBRARY_DIRS: $SNAP/etc/glvnd/egl_vendor.d:$SNAP/usr/share/glvnd/egl_vendor.d
  # XKB config
  XKB_CONFIG_ROOT: ${SNAP}/usr/share/X11/xkb
  # Qt Platform to Wayland
  QT_QPA_PLATFORM: wayland
  QT_QPA_PLATFORM_PLUGIN_PATH: ${SNAP}/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/qt5/plugins/platforms/
  QTCHOOSER_NO_GLOBAL_DIR: 1
  QT_SELECT: snappy-qt5
  # Qt Modules
  QT_PLUGIN_PATH: ${SNAP}/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/qt5/plugins
  QML2_IMPORT_PATH: ${SNAP}/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/qt5/qml
  # XDG Config
  XDG_CONFIG_DIRS: ${SNAP}/etc/xdg:$XDG_CONFIG_DIRS
  XDG_DATA_DIRS: ${SNAP}/usr/share:$XDG_DATA_DIRS
  # Needed for fontconfig
  XDG_DATA_HOME: ${SNAP}/usr/share
  FONTCONFIG_PATH: ${SNAP}/etc/fonts/conf.d
  FONTCONFIG_FILE: ${SNAP}/etc/fonts/fonts.conf
  # GL Config
  LIBGL_DRIVERS_PATH: ${SNAP}/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/dri

parts: # programs, libraries, assets,...

  qtwayland:
    plugin: nil
    stage-packages:
      - qtwayland5

  qt5:
    plugin: nil
    build-packages:
      - build-essential
      - qtbase5-dev
      - qt5-default
      - libqt5quick5
      - qtdeclarative5-dev
      - qtquickcontrols2-5-dev
      - dpkg-dev
    stage-packages:
      - libqt5qml5
      - libqt5quick5
      - libqt5quickcontrols2-5
      - libqt5quicktemplates2-5
      - qml-module-qtquick-layouts
      - qml-module-qtquick-controls
      - qml-module-qtquick-controls2
      - qml-module-qtquick-extras
      - libxkbcommon0
      - ttf-ubuntu-font-family
      - dmz-cursor-theme
      - light-themes
      - adwaita-icon-theme
      - gnome-themes-standard
      - shared-mime-info
      - libqt5gui5
      - libgdk-pixbuf2.0-0
      - libpsm-infinipath1
      - libpsm-infinipath1-dev
      - libgtk2.0-0
      - libqt5svg5 # for loading icon themes which are svg
      #- try: [appmenu-qt5] # not available on core18
      - locales-all
      - xdg-user-dirs
      - fcitx-frontend-qt5

  qtchooser-config:
    plugin: dump
    source: snap/local/qtconfig
    organize:
      snappy-qt5.conf: etc/xdg/qtchooser/snappy-qt5.conf

  mir-kiosk-snap-launch:
    plugin: dump
    source: https://github.com/MirServer/mir-kiosk-snap-launch.git
    override-build: $SNAPCRAFT_PART_BUILD/build-with-plugs.sh opengl wayland

  workspace:
    plugin: catkin-tools
    source: .
    catkin-packages: [catkin_simple, ads_catkin, eigen_catkin, mag_msgs, nav_controller, nav_gui]
    after: [qt5]

well … you probably want to add the network plug (and perhaps also network-bind if your app uses any kind of sockets …

did you try installing it with --devode to turn off confinement temporarily ?

You are right, with confinement I needed to add network and network-bind, which are probably used by the ROS system.

I had the same error launching ROS (https://www.ros.org/) using docker-compose.

The error was:

RLException: cannot resolve host address for machine [localhost]

In my docker-compose.yml file I had network=host. I just removed that line and the problem has gone away.

I am also trying to run hello world app in Kiosk mode. I can run app using miral-app and miral-kiosk. But I want run it as mir-kiosk-apps in fullscreen and as a daemon. I referred both the links posted in this topic.
I am installing the snap using snap install --dangerous --devmode ./*.snap and then running with " snap run cs-alto" then getting the same message on terminal as follows

a@a-Latitude-3480:~/test_kiosk_qello$ snap run cs-alto

  • dirname /run/user/1000/snap.cs-alto
  • real_wayland=/run/user/1000/wayland-0
  • [ ! -O /run/user/1000/wayland-0 ]
  • echo waiting for Wayland socket
    waiting for Wayland socket
  • sleep 4
  • [ ! -O /run/user/1000/wayland-0 ]
  • echo waiting for Wayland socket
    waiting for Wayland socket
  • sleep 4

My yaml file is as follows.

ame: cs-alto # you probably want to 'snapcraft register <name>'

base: core18 # the base snap is the execution environment for this snap
version: ‘0.1’ # just for humans, typically ‘1.2+git’ or ‘1.3.2’
summary: Control software example for packing with cqtdeployer # 79 char long summary
description: |
Control software example for packing with cqtdeployer

grade: stable # must be ‘stable’ to release into candidate/stable channels
confinement: strict # use ‘strict’ once you have the right plugs and slots

apps:
cs-alto:
command: wayland-launch $SNAP/qello.sh
plugs: [desktop, unity7, home, opengl, x11, wayland]

daemon:
daemon: simple
restart-condition: always
stop-timeout: “20s”
command: run-daemon wayland-launch $SNAP/qello.sh
plugs: [desktop, unity7, home, opengl, x11, wayland]

environment:
__EGL_VENDOR_LIBRARY_DIRS: $SNAP/etc/glvnd/egl_vendor.d:$SNAP/usr/share/glvnd/egl_vendor.d
QT_QPA_PLATFORM: wayland
#QT_QPA_PLATFORM: xcb
QTCHOOSER_NO_GLOBAL_DIR: 1
QT_SELECT: snappy-qt5
DISABLE_WAYLAND: 1
# Qt Modules
LD_LIBRARY_PATH: $SNAP/Qt/5.14.2/gcc_64/lib:$LD_LIBRARY_PATH
QT_PLUGIN_PATH: $SNAP/Qt/5.14.2/gcc_64/plugins
QML2_IMPORT_PATH: $QML2_IMPORT_PATH:$SNAP/Qt/5.14.2/gcc_64/qml
QT_QPA_PLATFORM_PLUGIN_PATH: $SNAP/Qt/5.14.2/gcc_64/plugins/platforms
# XDG Config
XDG_CONFIG_DIRS: $SNAP/etc/xdg:$SNAP/usr/xdg:$XDG_CONFIG_DIRS
XDG_DATA_DIRS: $SNAP/usr/share:$XDG_DATA_DIRS
# Font Config and themes
FONTCONFIG_PATH: $SNAP/etc/fonts/conf.d
FONTCONFIG_FILE: $SNAP/etc/fonts/fonts.conf
# Tell libGL where to find the drivers
LIBGL_DRIVERS_PATH: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/dri
#command: desktop-launch $SNAP/qello.sh

parts:
cs-alto:
# See ‘snapcraft plugins’
plugin: dump
source: ./distro
after: [wrapper, libsgl]

wrapper:
plugin: dump
source: wrapper

libsgl:
plugin: nil
stage-packages:
# Here for the plugins-- they’re not linked in automatically.
- libx11-xcb1
- libglu1-mesa
- libxrender1
- libxi6
- libegl1-mesa
- fontconfig
- libgl1-mesa-dri
- libxkbcommon0
- ttf-ubuntu-font-family
- dmz-cursor-theme
- adwaita-icon-theme
- gnome-themes-standard
- shared-mime-info
- libgdk-pixbuf2.0-0
- libgtk2.0-0
- xdg-user-dirs
- libxrandr2
- libwayland-cursor0
- libwayland-egl1
- libpq5
- qtwayland5

mir-kiosk-snap-launch:
plugin: dump
source: https://github.com/MirServer/mir-kiosk-snap-launch.git
override-build: $SNAPCRAFT_PART_BUILD/build-with-plugs.sh alsa avahi-observe hardware-observe locale-control mount-observe network-observe removable-media shutdown system-observe wayland
mesa:
plugin: nil
stage-packages:
- libgl1-mesa-dri
- libwayland-egl1-mesa
- libglu1-mesa

I have also installed mir-kiosk and tried following commands.
snap set cs-alto daemon=true
snap restart cs-alto

But it does not run in kiosk mode.

`

You’re running as the current user, and apparently don’t have a Wayland compositor running for that user. If you look at the tutorial you’ll see that you need to install and run a Wayland compositor such as miral kiosk (you can also use mir-kiosk if you’ve already installed that).

You’re running on a classic system, so by default the mir-kiosk daemon will not start. That also needs daemon=true to override this default. Beware that doing this will take control of your display and switch it to a VT on which mir-kiosk is running. (You can VT switch and stop the session, but it can be a surprise if you’re not expecting it.)

Thanks for the input. I tried with Wayland compositor. miral-app and miral-kiosk. It worked but not full screen. When I tried the link mentioned and executed the command " miral-app -kiosk -launcher '/path/to/my_application " for full screen.

I got following error
a@a-Latitude-3480:~/test_glmark2_example$ miral-app -kiosk -launcher ‘glmark2-wayland --fullscreen’

[2020-10-22 09:27:19.749191] mirserver: . |_ Orientation normal
[2020-10-22 09:27:19.749201] mirserver: . |_ Logical size 1216x618
[2020-10-22 09:27:19.749208] mirserver: . |_ Logical position +0+0
[2020-10-22 09:27:19.749217] mirserver: . |_ Scaling factor: 1.00
Display does not support owner-change; copy/paste will be broken!
[2020-10-22 09:27:21.198278] < - debug - > mirserver: Handling Terminated from pid=10474
a@a-Latitude-3480:~/test_glmark2_example$ [2020-10-22 09:27:21.798817] < - debug - > wayland-gfx-helpers: Wayland buffer destroyed before use; rendering will be incomplete
Gdk-Message: 09:27:21.826: Error flushing display: Broken pipe
^C
a@a-Latitude-3480:~/test_glmark2_example$

You’re running on a classic system, so by default the mir-kiosk daemon will not start. That also needs daemon=true to override this default. Beware that doing this will take control of your display and switch it to a VT on which mir-kiosk is running. (You can VT switch and stop the session, but it can be a surprise if you’re not expecting it.)

For this I ran following sequence of commands.

  1. sudo snap set mir-kiosk daemon=true
  2. sudo snap set cs-alto daemon=true
  3. sudo snap cs-alto restart
  4. reboot

After system was rebooted and went into daemon mode but screen was blank it did not display application. I need to the app like mir-kiosk-apps. What I will need to do?

check your system journal for application errors, check the snap connections of your app snap, run snappy-debug (from the snappy-debug snap) in one terminal while restarting the app from another …