├── gtk
├── init
├── mark-and-exec
├── desktop-exports
├── snapcraft.yaml
├── runtime-exports
├── Makefile
└── launcher-specific
├── qt
├── init
├── runtime-exports
├── desktop-exports
├── mark-and-exec
├── snapcraft.yaml
├── Makefile
└── launcher-specific
├── glib-only
├── init
├── mark-and-exec
├── desktop-exports
├── launcher-specific
└── Makefile
├── .gitignore
├── demos
├── qt5
│ ├── src
│ │ ├── images
│ │ │ ├── copy.png
│ │ │ ├── cut.png
│ │ │ ├── new.png
│ │ │ ├── open.png
│ │ │ ├── paste.png
│ │ │ └── save.png
│ │ ├── application.pro
│ │ ├── application.qrc
│ │ ├── main.cpp
│ │ ├── mainwindow.h
│ │ └── mainwindow.cpp
│ ├── snap
│ │ └── gui
│ │ │ ├── qt5-application.png
│ │ │ └── qt5-application.desktop
│ └── snapcraft.yaml
├── gtk2
│ └── snapcraft.yaml
└── gtk3
│ └── snapcraft.yaml
├── common
├── mark-and-exec
├── init
└── desktop-exports
├── Dockerfile
├── LICENSE
├── README.md
├── src
└── bindtextdomain.c
└── snapcraft.yaml
/gtk/init:
--------------------------------------------------------------------------------
1 | ../common/init
--------------------------------------------------------------------------------
/qt/init:
--------------------------------------------------------------------------------
1 | ../common/init
--------------------------------------------------------------------------------
/qt/runtime-exports:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/glib-only/init:
--------------------------------------------------------------------------------
1 | ../common/init
--------------------------------------------------------------------------------
/gtk/mark-and-exec:
--------------------------------------------------------------------------------
1 | ../common/mark-and-exec
--------------------------------------------------------------------------------
/qt/desktop-exports:
--------------------------------------------------------------------------------
1 | ../common/desktop-exports
--------------------------------------------------------------------------------
/qt/mark-and-exec:
--------------------------------------------------------------------------------
1 | ../common/mark-and-exec
--------------------------------------------------------------------------------
/glib-only/mark-and-exec:
--------------------------------------------------------------------------------
1 | ../common/mark-and-exec
--------------------------------------------------------------------------------
/gtk/desktop-exports:
--------------------------------------------------------------------------------
1 | ../common/desktop-exports
--------------------------------------------------------------------------------
/glib-only/desktop-exports:
--------------------------------------------------------------------------------
1 | ../common/desktop-exports
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/parts
2 | **/stage
3 | **/snap
4 | **/prime
5 | **/*.snap
6 | **/*.tar*
7 |
--------------------------------------------------------------------------------
/demos/qt5/src/images/copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ubuntu/snapcraft-desktop-helpers/HEAD/demos/qt5/src/images/copy.png
--------------------------------------------------------------------------------
/demos/qt5/src/images/cut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ubuntu/snapcraft-desktop-helpers/HEAD/demos/qt5/src/images/cut.png
--------------------------------------------------------------------------------
/demos/qt5/src/images/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ubuntu/snapcraft-desktop-helpers/HEAD/demos/qt5/src/images/new.png
--------------------------------------------------------------------------------
/demos/qt5/src/images/open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ubuntu/snapcraft-desktop-helpers/HEAD/demos/qt5/src/images/open.png
--------------------------------------------------------------------------------
/demos/qt5/src/images/paste.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ubuntu/snapcraft-desktop-helpers/HEAD/demos/qt5/src/images/paste.png
--------------------------------------------------------------------------------
/demos/qt5/src/images/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ubuntu/snapcraft-desktop-helpers/HEAD/demos/qt5/src/images/save.png
--------------------------------------------------------------------------------
/glib-only/launcher-specific:
--------------------------------------------------------------------------------
1 | ##############################
2 | # Glib minimum specific part #
3 | ##############################
4 |
5 |
--------------------------------------------------------------------------------
/demos/qt5/snap/gui/qt5-application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ubuntu/snapcraft-desktop-helpers/HEAD/demos/qt5/snap/gui/qt5-application.png
--------------------------------------------------------------------------------
/demos/qt5/src/application.pro:
--------------------------------------------------------------------------------
1 | QT += widgets
2 |
3 | HEADERS = mainwindow.h
4 | SOURCES = main.cpp \
5 | mainwindow.cpp
6 | #! [0]
7 | RESOURCES = application.qrc
8 | #! [0]
9 |
10 | # install
11 | target.path = /bin
12 | INSTALLS += target
13 |
--------------------------------------------------------------------------------
/demos/qt5/src/application.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | images/copy.png
4 | images/cut.png
5 | images/new.png
6 | images/open.png
7 | images/paste.png
8 | images/save.png
9 |
10 |
11 |
--------------------------------------------------------------------------------
/gtk/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: gtk
2 | version: 0.1
3 | summary: This is meant to be consumed by other projects
4 | description: |
5 | This sets up the GTK environment for GTK-based projects and its dependencies
6 | confinement: strict
7 |
8 | parts:
9 | gtk:
10 | source: .
11 | plugin: make
12 | make-parameters: ["SRC_DIR=../src", "FLAVOR=gtk2"]
13 |
--------------------------------------------------------------------------------
/demos/qt5/snap/gui/qt5-application.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Encoding=UTF-8
3 | Name=Qt5App
4 | GenericName=A simple text editor
5 | Comment=A simple text editor
6 | Exec=qt5-application
7 | Icon=${SNAP}/meta/gui/qt5-application.png
8 | Terminal=false
9 | Type=Application
10 | StartupNotify=false
11 | Categories=Application;Game
12 | Keywords=mc-installer;
13 |
--------------------------------------------------------------------------------
/common/mark-and-exec:
--------------------------------------------------------------------------------
1 | ###############################
2 | # Mark update and exec binary #
3 | ###############################
4 |
5 | [ $needs_update = true ] && echo "SNAP_DESKTOP_LAST_REVISION=$SNAP_REVISION" > $SNAP_USER_DATA/.last_revision
6 |
7 | wait_for_async_execs
8 |
9 | if [ -n "$SNAP_DESKTOP_DEBUG" ]; then
10 | echo "desktop-launch elapsed time: " $(date +%s.%N --date="$START seconds ago")
11 | echo "Now running: exec $@"
12 | fi
13 |
14 | exec "$@"
15 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM snapcore/snapcraft:stable
2 |
3 | RUN apt-get install -q -y --no-install-recommends software-properties-common && \
4 | add-apt-repository -yu ppa:ubuntu-desktop/gnome-3-26 && \
5 | apt-get update && \
6 | apt-get dist-upgrade --yes && \
7 | apt-get install --yes \
8 | build-essential \
9 | libgtk-3-dev \
10 | snapcraft \
11 | && \
12 | apt-get autoclean --yes && \
13 | apt-get clean --yes
14 |
15 | # Required by click.
16 | ENV LC_ALL C.UTF-8
17 | ENV SNAPCRAFT_SETUP_CORE 1
18 |
--------------------------------------------------------------------------------
/demos/gtk2/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: gtk2-demo
2 | version: "0"
3 | summary: Gtk2 launcher demo
4 | description: This is using the gtk2 demo
5 | grade: stable
6 | confinement: strict
7 |
8 | apps:
9 | gtk2-demo:
10 | command: desktop-launch gtk-demo
11 | plugs: [unity7, x11, gsettings, home]
12 | gsettings:
13 | command: desktop-launch gsettings
14 | plugs: [x11, gsettings, home]
15 |
16 | parts:
17 | gtk2-demo:
18 | plugin: nil
19 | stage-packages: [gtk2.0-examples, libglib2.0-bin]
20 | after: [desktop-gtk2]
21 |
--------------------------------------------------------------------------------
/glib-only/Makefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 |
3 | SRC_DIR ?= .
4 |
5 | DEST_LAUNCHER = desktop-launch
6 |
7 | build: $(DEST_LAUNCHER)
8 |
9 | clean:
10 | rm -f $(DEST_LAUNCHER)
11 |
12 | $(DEST_LAUNCHER):
13 | @echo "#!/bin/bash" > $(DEST_LAUNCHER)
14 | @cat $(SRC_DIR)/init >> $(DEST_LAUNCHER)
15 | @cat $(SRC_DIR)/desktop-exports >> $(DEST_LAUNCHER)
16 | @cat $(SRC_DIR)/launcher-specific >> $(DEST_LAUNCHER)
17 | @cat $(SRC_DIR)/mark-and-exec >> $(DEST_LAUNCHER)
18 |
19 | install: $(DEST_LAUNCHER)
20 | install -D -m755 $(DEST_LAUNCHER) "$(DESTDIR)"/bin/$(DEST_LAUNCHER)
21 |
--------------------------------------------------------------------------------
/qt/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: application
2 | version: 1
3 | summary: Qt Application Example
4 | description: A simple text editor
5 | confinement: devmode
6 |
7 | apps:
8 | application:
9 | command: desktop-launch application
10 | plugs: [unity7, home]
11 |
12 | parts:
13 | application:
14 | source: src/
15 | plugin: qmake
16 | qt-version: qt5
17 | after: [qt5]
18 | qt5:
19 | source: .
20 | plugin: make
21 | make-parameters: ["SRC_DIR=../src"]
22 | build-packages:
23 | - qtbase5-dev
24 | - dpkg-dev
25 | stage-packages:
26 | - libxkbcommon0
27 | - ttf-ubuntu-font-family
28 | - dmz-cursor-theme
29 | - light-themes
30 | - shared-mime-info
31 | - libqt5gui5
32 | - libgdk-pixbuf2.0-0
33 | - libqt5svg5 # for loading icon themes which are svg
34 | - appmenu-qt5
35 |
36 |
--------------------------------------------------------------------------------
/gtk/runtime-exports:
--------------------------------------------------------------------------------
1 | ###########################
2 | # GNOME runtime selection #
3 | ###########################
4 |
5 | if [ -d $SNAP/gnome-platform ]; then
6 | RUNTIME=$SNAP/gnome-platform
7 | if [ ! -d $RUNTIME/usr ]; then
8 | platform_snap_name="$(
9 | grep \
10 | --extended-regexp \
11 | 'default-provider: *gnome-[[:digit:]]+-[[:digit:]]+-[[:digit:]]+' \
12 | $SNAP/meta/snap.yaml \
13 | | cut --delimiter=: --fields=2 \
14 | | sed 's/^ *//' \
15 | || true
16 | )"
17 |
18 | if test -n "${platform_snap_name}"; then
19 | echo "You need to connect this snap to the gnome platform snap."
20 | echo ""
21 | echo "You can do this with those commands:"
22 | echo "snap install ${platform_snap_name}"
23 | echo "snap connect $SNAP_NAME:${platform_snap_name} ${platform_snap_name}"
24 | echo ""
25 | exit 1
26 | fi
27 | fi
28 | fi
29 |
30 |
--------------------------------------------------------------------------------
/gtk/Makefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 |
3 | FLAVOR ?= gtk3
4 | SRC_DIR ?= .
5 |
6 | DEST_LAUNCHER = desktop-launch
7 | FLAVOR_FILE = flavor-select
8 | BINDTEXTDOMAIN = bindtextdomain.so
9 |
10 | build: $(DEST_LAUNCHER)
11 |
12 | clean:
13 | rm -f $(DEST_LAUNCHER)
14 | rm -f $(FLAVOR_FILE)
15 | rm -f $(BINDTEXTDOMAIN)
16 |
17 | $(DEST_LAUNCHER):
18 | @echo "#!/bin/bash" > $(DEST_LAUNCHER)
19 | @cat $(SRC_DIR)/init >> $(DEST_LAUNCHER)
20 | @cat $(SRC_DIR)/runtime-exports >> $(DEST_LAUNCHER)
21 | @cat $(SRC_DIR)/desktop-exports >> $(DEST_LAUNCHER)
22 | @cat $(SRC_DIR)/launcher-specific >> $(DEST_LAUNCHER)
23 | @cat $(SRC_DIR)/mark-and-exec >> $(DEST_LAUNCHER)
24 | @echo "USE_$(FLAVOR)=true" >> $(FLAVOR_FILE)
25 | gcc -Wall -O2 -o $(BINDTEXTDOMAIN) -fPIC -shared $(SRC_DIR)/../src/bindtextdomain.c -ldl
26 |
27 | install: $(DEST_LAUNCHER)
28 | install -D -m755 $(DEST_LAUNCHER) "$(DESTDIR)"/bin/$(DEST_LAUNCHER)
29 | install -D -m644 $(FLAVOR_FILE) "$(DESTDIR)"/
30 | install -D -m644 $(BINDTEXTDOMAIN) "$(DESTDIR)"/lib/$(BINDTEXTDOMAIN)
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Canonical
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/gtk/launcher-specific:
--------------------------------------------------------------------------------
1 | ##############################
2 | # GTK launcher specific part #
3 | ##############################
4 |
5 | # select gtk version
6 | . $SNAP/flavor-select
7 |
8 | if [ "$USE_gtk3" = true ]; then
9 | if [ "$wayland_available" = true ]; then
10 | export GDK_BACKEND="wayland"
11 | export CLUTTER_BACKEND="wayland"
12 | # Does not hurt to specify this as well, just in case
13 | export QT_QPA_PLATFORM=wayland-egl
14 | fi
15 | append_dir GTK_PATH $RUNTIME/usr/lib/$ARCH/gtk-3.0
16 | else
17 | [ "$wayland_available" = true ] && echo "Warning: GTK2 does not support Wayland!"
18 | append_dir GTK_PATH $RUNTIME/usr/lib/$ARCH/gtk-2.0
19 | fi
20 |
21 | # ibus and fcitx integration
22 | GTK_IM_MODULE_DIR=$XDG_CACHE_HOME/immodules
23 | export GTK_IM_MODULE_FILE=$GTK_IM_MODULE_DIR/immodules.cache
24 | if [ $needs_update = true ]; then
25 | rm -rf $GTK_IM_MODULE_DIR
26 | ensure_dir_exists $GTK_IM_MODULE_DIR
27 | if [ "$USE_gtk3" = true ]; then
28 | ln -s $RUNTIME/usr/lib/$ARCH/gtk-3.0/3.0.0/immodules/*.so $GTK_IM_MODULE_DIR
29 | async_exec $RUNTIME/usr/lib/$ARCH/libgtk-3-0/gtk-query-immodules-3.0 > $GTK_IM_MODULE_FILE
30 | else
31 | ln -s $RUNTIME/usr/lib/$ARCH/gtk-2.0/2.10.0/immodules/*.so $GTK_IM_MODULE_DIR
32 | async_exec $RUNTIME/usr/lib/$ARCH/libgtk2.0-0/gtk-query-immodules-2.0 > $GTK_IM_MODULE_FILE
33 | fi
34 | fi
35 |
36 |
--------------------------------------------------------------------------------
/qt/Makefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 |
3 | FLAVOR ?= qt5
4 | SRC_DIR ?= .
5 |
6 | DEST_LAUNCHER = desktop-launch
7 | FLAVOR_FILE = flavor-select
8 |
9 | arch_triplet := $(shell dpkg-architecture -q DEB_TARGET_MULTIARCH)
10 |
11 | define QT5_CONF
12 | ./usr/lib/$(arch_triplet)/qt5/bin
13 | ./usr/lib/$(arch_triplet)
14 | endef
15 | export QT5_CONF
16 |
17 | define QT4_CONF
18 | ./usr/lib/$(arch_triplet)/qt4/bin
19 | ./usr/lib/$(arch_triplet)
20 | endef
21 | export QT4_CONF
22 |
23 |
24 | build: $(DEST_LAUNCHER)
25 |
26 | clean:
27 | rm -f $(DEST_LAUNCHER)
28 | rm -rf snappy-qt*.conf
29 | rm -f $(FLAVOR_FILE)
30 |
31 | desktop-launch:
32 | @echo "#!/bin/bash" > $(DEST_LAUNCHER)
33 | @cat $(SRC_DIR)/init >> $(DEST_LAUNCHER)
34 | @cat $(SRC_DIR)/runtime-exports >> $(DEST_LAUNCHER)
35 | @cat $(SRC_DIR)/desktop-exports >> $(DEST_LAUNCHER)
36 | @cat $(SRC_DIR)/launcher-specific >> $(DEST_LAUNCHER)
37 | @cat $(SRC_DIR)/mark-and-exec >> $(DEST_LAUNCHER)
38 | @echo "$$QT5_CONF" > snappy-qt5.conf
39 | @echo "$$QT4_CONF" > snappy-qt4.conf
40 | @echo "USE_$(FLAVOR)=true" >> $(FLAVOR_FILE)
41 |
42 | install: desktop-launch
43 | install -D -m755 $(DEST_LAUNCHER) "$(DESTDIR)"/bin/$(DEST_LAUNCHER)
44 | install -D -m644 snappy-qt5.conf \
45 | "$(DESTDIR)"/etc/xdg/qtchooser/snappy-qt5.conf
46 | install -D -m644 snappy-qt4.conf \
47 | "$(DESTDIR)"/etc/xdg/qtchooser/snappy-qt4.conf
48 | install -D -m644 $(FLAVOR_FILE) "$(DESTDIR)"/
49 |
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DEPRECATED -- Use gnome or kde-neon extension
2 |
3 | The snapcraft desktop helpers are no longer support please use one of the following snapcraft extensions
4 | * [GNOME (for GTK or apps that require typical desktop support)](https://documentation.ubuntu.com/snapcraft/stable/reference/extensions/gnome-extension/)
5 | * [KDE (for KDE or Qt)](https://documentation.ubuntu.com/snapcraft/stable/reference/extensions/kde-neon-extensions/)
6 |
7 | # Snapcraft Desktop Helpers
8 |
9 | The snapcraft desktop helpers project contains a number of tools to help you create snaps for desktop applications. For example, several environment variables and compatibility symlinks are setup in the [desktop-launch wrapper](https://github.com/ubuntu/snapcraft-desktop-helpers/blob/master/common/desktop-exports) to help ensure the snap can find needed files.
10 |
11 | ## How to use the desktop helpers
12 |
13 | Go to the documentation on [snapping graphical applications](https://forum.snapcraft.io/t/desktop-applications/13034) and follow the instructions for the GUI toolkit that your application uses.
14 |
15 | > ℹ️ We are currently in the process of moving most of the functionality of the desktop helpers to [Snapcraft Extensions](https://forum.snapcraft.io/t/snapcraft-extensions/13486). The extensions are much easier to use and contain many improvements, so it's advised to use an extension if one is available for the GUI toolkit that you use.
16 |
17 | ## Need help?
18 |
19 | Please feel free to ask questions in the [forum](https://forum.snapcraft.io) if you are having trouble.
20 |
--------------------------------------------------------------------------------
/demos/gtk3/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: gtk3-demo
2 | version: "3.18"
3 | summary: Gtk3 launcher demo
4 | description: |
5 | Use the gtk3 demo to show desktop launcher properties with all libraries included.
6 | grade: stable
7 | confinement: strict
8 | base: core18
9 |
10 | apps:
11 | gtk3-demo:
12 | command: bin/desktop-launch gtk3-demo
13 | plugs:
14 | - desktop
15 | - desktop-legacy
16 | - wayland
17 | - x11
18 | - unity7
19 | - gsettings # For desktop theme detection under Wayland session
20 | - home
21 | gsettings:
22 | command: bin/desktop-launch gsettings
23 | plugs:
24 | - gsettings
25 |
26 | parts:
27 | gtk3-demo:
28 | plugin: nil
29 | stage-packages: [gtk-3-examples, libglib2.0-bin]
30 | after: [desktop-gnome-platform]
31 |
32 | # This part installs the `desktop-launch` script which initialises desktop
33 | # features such as fonts, themes and the XDG environment.
34 | #
35 | # It is copied straight from the snapcraft desktop helpers project. Please
36 | # periodically check the source for updates and copy the changes.
37 | # https://github.com/ubuntu/snapcraft-desktop-helpers/blob/master/snapcraft.yaml
38 | #
39 | desktop-gnome-platform:
40 | source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
41 | source-subdir: gtk
42 | plugin: make
43 | make-parameters: ["FLAVOR=gtk3"]
44 | build-packages:
45 | - gcc
46 | override-build: |
47 | snapcraftctl build
48 | mkdir -pv $SNAPCRAFT_PART_INSTALL/gnome-platform
49 |
50 | plugs:
51 | gnome-3-28-1804:
52 | interface: content
53 | target: $SNAP/gnome-platform
54 | default-provider: gnome-3-28-1804
55 | gtk-3-themes:
56 | interface: content
57 | target: $SNAP/data-dir/themes
58 | default-provider: gtk-common-themes
59 | icon-themes:
60 | interface: content
61 | target: $SNAP/data-dir/icons
62 | default-provider: gtk-common-themes
63 | sound-themes:
64 | interface: content
65 | target: $SNAP/data-dir/sounds
66 | default-provider: gtk-common-themes
67 |
--------------------------------------------------------------------------------
/qt/launcher-specific:
--------------------------------------------------------------------------------
1 | #############################
2 | # QT launcher specific part #
3 | #############################
4 |
5 | # select qt version
6 | . $SNAP/flavor-select
7 |
8 | export QTCHOOSER_NO_GLOBAL_DIR=1
9 | if [ "$USE_qt5" = true ]; then
10 | # QT_SELECT not exported by ubuntu app platform runtime
11 | if [ -z "$QT_SELECT" ]; then
12 | export QT_SELECT=snappy-qt5
13 | fi
14 | else
15 | export QT_SELECT=snappy-qt4
16 | fi
17 |
18 | # Removes Qt warning: Could not find a location
19 | # of the system Compose files
20 | export QTCOMPOSE=$RUNTIME/usr/share/X11/locale
21 |
22 | # Qt Libs, Modules and helpers
23 | if [ "$USE_qt5" = true ]; then
24 | prepend_dir QT_PLUGIN_PATH $RUNTIME/usr/lib/$ARCH/qt5/plugins
25 | prepend_dir QML2_IMPORT_PATH $RUNTIME/usr/lib/$ARCH/qt5/qml
26 | prepend_dir QML2_IMPORT_PATH $RUNTIME/lib/$ARCH
27 | # Try to use qtubuntu-print plugin, if not found Qt will fallback to the first found (usually cups plugin)
28 | export QT_PRINTER_MODULE=qtubuntu-print
29 | if [ "$WITH_RUNTIME" = yes ]; then
30 | prepend_dir QML2_IMPORT_PATH $SNAP/usr/lib/$ARCH/qt5/qml
31 | prepend_dir QML2_IMPORT_PATH $SNAP/lib/$ARCH
32 | fi
33 | prepend_dir PATH $RUNTIME/usr/lib/$ARCH/qt5/bin
34 |
35 | if [ "$wayland_available" = true ]; then
36 | export QT_QPA_PLATFORM=wayland-egl
37 | # Does not hurt to specify these as well, just in case
38 | export GDK_BACKEND="wayland"
39 | export CLUTTER_BACKEND="wayland"
40 | else
41 | # Should check if a X11 $DISPLAY variable is set and accessible
42 | export QT_QPA_PLATFORM=xcb
43 | if ! [ -v QT_QPA_PLATFORMTHEME ] || [ -z "${QT_QPA_PLATFORMTHEME}" ]; then
44 | export QT_QPA_PLATFORMTHEME=appmenu-qt5
45 | fi
46 | fi
47 |
48 | else
49 | [ "$wayland_available" = true ] && echo "Warning: Qt4 does not support Wayland!"
50 | append_dir LD_LIBRARY_PATH $SNAP/usr/lib/$ARCH/qt4
51 | export QT_PLUGIN_PATH=$SNAP/usr/lib/$ARCH/qt4/plugins
52 | prepend_dir QML_IMPORT_PATH $SNAP/usr/lib/$ARCH/qt4/qml:$SNAP/lib/$ARCH
53 | prepend_dir PATH $SNAP/usr/lib/$ARCH/qt4/bin
54 | fi
55 |
56 | # Use GTK styling for running under the GNOME desktop
57 | append_dir GTK_PATH $RUNTIME/usr/lib/$ARCH/gtk-2.0
58 |
59 | # Fix locating the QtWebEngineProcess executable
60 | export QTWEBENGINEPROCESS_PATH=$RUNTIME/usr/lib/$ARCH/qt5/libexec/QtWebEngineProcess
61 |
--------------------------------------------------------------------------------
/demos/qt5/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: qt5-application
2 | version: "2"
3 | summary: Qt5 Application Example
4 | description: A simple text editor
5 | grade: stable
6 | confinement: strict
7 | base: core18
8 | icon: snap/gui/qt5-application.png
9 |
10 | apps:
11 | qt5-application:
12 | environment:
13 | # Use GTK3 cursor theme, icon theme and open/save file dialogs.
14 | QT_QPA_PLATFORMTHEME: gtk3
15 | command: desktop-launch application
16 | plugs: [unity7, home]
17 |
18 | parts:
19 | application:
20 | source: src/
21 | plugin: qmake
22 | qt-version: qt5
23 | after: [desktop-qt5]
24 |
25 | # This part installs the qt5 dependencies and the `desktop-launch` script
26 | # which initialises desktop features such as fonts, themes and the XDG
27 | # environment.
28 | #
29 | # It is copied straight from the snapcraft desktop helpers project. Please
30 | # periodically check the source for updates and copy the changes.
31 | # https://github.com/ubuntu/snapcraft-desktop-helpers/blob/master/snapcraft.yaml
32 | #
33 | desktop-qt5:
34 | source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
35 | source-subdir: qt
36 | plugin: make
37 | make-parameters: ["FLAVOR=qt5"]
38 | build-packages:
39 | - build-essential
40 | - qtbase5-dev
41 | - dpkg-dev
42 | stage-packages:
43 | - libxkbcommon0
44 | - ttf-ubuntu-font-family
45 | - dmz-cursor-theme
46 | - light-themes
47 | - adwaita-icon-theme
48 | - gnome-themes-standard
49 | - shared-mime-info
50 | - libqt5gui5
51 | - libgdk-pixbuf2.0-0
52 | - libqt5svg5 # for loading icon themes which are svg
53 | - try: [appmenu-qt5] # not available on core18
54 | - locales-all
55 | - xdg-user-dirs
56 | - fcitx-frontend-qt5
57 |
58 | qt5-gtk-platform:
59 | plugin: nil
60 | stage-packages:
61 | - qt5-gtk-platformtheme
62 |
63 | plugs:
64 | # Support for common GTK themes
65 | # https://forum.snapcraft.io/t/how-to-use-the-system-gtk-theme-via-the-gtk-common-themes-snap/6235
66 | gsettings:
67 | gtk-3-themes:
68 | interface: content
69 | target: $SNAP/data-dir/themes
70 | default-provider: gtk-common-themes
71 | icon-themes:
72 | interface: content
73 | target: $SNAP/data-dir/icons
74 | default-provider: gtk-common-themes
75 | sound-themes:
76 | interface: content
77 | target: $SNAP/data-dir/sounds
78 | default-provider: gtk-common-themes
79 |
--------------------------------------------------------------------------------
/common/init:
--------------------------------------------------------------------------------
1 | #################
2 | # Launcher init #
3 | #################
4 |
5 | START=$(date +%s.%N)
6 |
7 | declare -A PIDS
8 | function async_exec() {
9 | $@ &
10 | PIDS[$!]=$@
11 | }
12 | function wait_for_async_execs() {
13 | for i in ${!PIDS[@]}
14 | do
15 | wait $i && continue || echo "ERROR: ${PIDS[$i]} exited abnormally with status $?"
16 | done
17 | }
18 |
19 | # ensure_dir_exists calls `mkdir -p` if the given path is not a directory.
20 | # This speeds up execution time by avoiding unnecessary calls to mkdir.
21 | #
22 | # Usage: ensure_dir_exists []...
23 | #
24 | function ensure_dir_exists() {
25 | [ -d "$1" ] || mkdir -p "$@"
26 | }
27 |
28 | # On Fedora $SNAP is under /var and there is some magic to map it to /snap.
29 | # # We need to handle that case and reset $SNAP
30 | SNAP=`echo $SNAP | sed -e "s|/var/lib/snapd||g"`
31 |
32 | needs_update=true
33 |
34 | . $SNAP_USER_DATA/.last_revision 2>/dev/null || true
35 | if [ "$SNAP_DESKTOP_LAST_REVISION" = "$SNAP_REVISION" ]; then
36 | needs_update=false
37 | fi
38 |
39 | # Set $REALHOME to the users real home directory
40 | REALHOME=`getent passwd $UID | cut -d ':' -f 6`
41 |
42 | # Set config folder to local path
43 | export XDG_CONFIG_HOME=$SNAP_USER_DATA/.config
44 | ensure_dir_exists $XDG_CONFIG_HOME -m 700
45 |
46 | # If the user has modified their user-dirs settings, force an update
47 | if [[ -f "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum" ]]; then
48 | if [[ "$(md5sum < "$REALHOME/.config/user-dirs.dirs")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum")" ||
49 | ( -f "$XDG_CONFIG_HOME/user-dirs.locale.md5sum" &&
50 | "$(md5sum < "$REALHOME/.config/user-dirs.locale")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.locale.md5sum")" ) ]]; then
51 | needs_update=true
52 | fi
53 | else
54 | needs_update=true
55 | fi
56 |
57 | if [ "$SNAP_ARCH" == "amd64" ]; then
58 | ARCH="x86_64-linux-gnu"
59 | elif [ "$SNAP_ARCH" == "armhf" ]; then
60 | ARCH="arm-linux-gnueabihf"
61 | elif [ "$SNAP_ARCH" == "arm64" ]; then
62 | ARCH="aarch64-linux-gnu"
63 | elif [ "$SNAP_ARCH" == "ppc64el" ]; then
64 | ARCH="powerpc64le-linux-gnu"
65 | else
66 | ARCH="$SNAP_ARCH-linux-gnu"
67 | fi
68 |
69 | export SNAP_LAUNCHER_ARCH_TRIPLET=$ARCH
70 |
71 | # Don't LD_PRELOAD bindtextdomain for classic snaps
72 | if ! grep -qs "^\s*confinement:\s*classic\s*" $SNAP/meta/snap.yaml; then
73 | if [ -f $SNAP/lib/bindtextdomain.so ]; then
74 | export LD_PRELOAD=$LD_PRELOAD:$SNAP/lib/bindtextdomain.so
75 | fi
76 | fi
77 |
--------------------------------------------------------------------------------
/demos/qt5/src/main.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 The Qt Company Ltd.
4 | ** Contact: http://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** You may use this file under the terms of the BSD license as follows:
10 | **
11 | ** "Redistribution and use in source and binary forms, with or without
12 | ** modification, are permitted provided that the following conditions are
13 | ** met:
14 | ** * Redistributions of source code must retain the above copyright
15 | ** notice, this list of conditions and the following disclaimer.
16 | ** * Redistributions in binary form must reproduce the above copyright
17 | ** notice, this list of conditions and the following disclaimer in
18 | ** the documentation and/or other materials provided with the
19 | ** distribution.
20 | ** * Neither the name of The Qt Company Ltd nor the names of its
21 | ** contributors may be used to endorse or promote products derived
22 | ** from this software without specific prior written permission.
23 | **
24 | **
25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 | **
37 | ** $QT_END_LICENSE$
38 | **
39 | ****************************************************************************/
40 |
41 | //! [0]
42 | #include
43 |
44 | #include "mainwindow.h"
45 |
46 | int main(int argc, char *argv[])
47 | {
48 | Q_INIT_RESOURCE(application);
49 |
50 | QApplication app(argc, argv);
51 | app.setOrganizationName("QtProject");
52 | app.setApplicationName("Application Example");
53 | MainWindow mainWin;
54 | mainWin.show();
55 | return app.exec();
56 | }
57 | //! [0]
58 |
--------------------------------------------------------------------------------
/demos/qt5/src/mainwindow.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 The Qt Company Ltd.
4 | ** Contact: http://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** You may use this file under the terms of the BSD license as follows:
10 | **
11 | ** "Redistribution and use in source and binary forms, with or without
12 | ** modification, are permitted provided that the following conditions are
13 | ** met:
14 | ** * Redistributions of source code must retain the above copyright
15 | ** notice, this list of conditions and the following disclaimer.
16 | ** * Redistributions in binary form must reproduce the above copyright
17 | ** notice, this list of conditions and the following disclaimer in
18 | ** the documentation and/or other materials provided with the
19 | ** distribution.
20 | ** * Neither the name of The Qt Company Ltd nor the names of its
21 | ** contributors may be used to endorse or promote products derived
22 | ** from this software without specific prior written permission.
23 | **
24 | **
25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 | **
37 | ** $QT_END_LICENSE$
38 | **
39 | ****************************************************************************/
40 |
41 | #ifndef MAINWINDOW_H
42 | #define MAINWINDOW_H
43 |
44 | #include
45 |
46 | QT_BEGIN_NAMESPACE
47 | class QAction;
48 | class QMenu;
49 | class QPlainTextEdit;
50 | QT_END_NAMESPACE
51 |
52 | //! [0]
53 | class MainWindow : public QMainWindow
54 | {
55 | Q_OBJECT
56 |
57 | public:
58 | MainWindow();
59 |
60 | protected:
61 | void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
62 |
63 | private slots:
64 | void newFile();
65 | void open();
66 | bool save();
67 | bool saveAs();
68 | void about();
69 | void documentWasModified();
70 |
71 | private:
72 | void createActions();
73 | void createMenus();
74 | void createToolBars();
75 | void createStatusBar();
76 | void readSettings();
77 | void writeSettings();
78 | bool maybeSave();
79 | void loadFile(const QString &fileName);
80 | bool saveFile(const QString &fileName);
81 | void setCurrentFile(const QString &fileName);
82 | QString strippedName(const QString &fullFileName);
83 |
84 | QPlainTextEdit *textEdit;
85 | QString curFile;
86 |
87 | QMenu *fileMenu;
88 | QMenu *editMenu;
89 | QMenu *helpMenu;
90 | QToolBar *fileToolBar;
91 | QToolBar *editToolBar;
92 | QAction *newAct;
93 | QAction *openAct;
94 | QAction *saveAct;
95 | QAction *saveAsAct;
96 | QAction *exitAct;
97 | QAction *cutAct;
98 | QAction *copyAct;
99 | QAction *pasteAct;
100 | QAction *aboutAct;
101 | QAction *aboutQtAct;
102 | };
103 | //! [0]
104 |
105 | #endif
106 |
--------------------------------------------------------------------------------
/src/bindtextdomain.c:
--------------------------------------------------------------------------------
1 | /* gcc -Wall -O2 -o bindtextdomain.so -fPIC -shared bindtextdomain.c -ldl */
2 |
3 | #define _GNU_SOURCE
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | static void die (const char *msg)
14 | {
15 | fprintf (stderr, "can't preload: %s\n", msg);
16 | exit (EXIT_FAILURE);
17 | }
18 |
19 | typedef char * (*BindTextDomainFunc) (const char *a,
20 | const char *b);
21 |
22 | static BindTextDomainFunc r_bindtextdomain = NULL;
23 |
24 | char *bindtextdomain(const char *domainname, const char *dirname)
25 | {
26 | char *snap = NULL;
27 | char *snap_path = NULL;
28 | char *snap_locale_path = NULL;
29 | DIR *dir = NULL;
30 | struct dirent *ent = NULL;
31 | char *ret = NULL;
32 |
33 | if (r_bindtextdomain == 0 && !(r_bindtextdomain =
34 | (BindTextDomainFunc) dlsym (RTLD_NEXT, "bindtextdomain")))
35 | die ("can't find symbol \"bindtextdomain\"");
36 |
37 | if (dirname == NULL || dirname[0] != '/')
38 | goto orig;
39 |
40 | snap = getenv ("SNAP");
41 |
42 | if (snap == NULL || strcmp (snap, "") == 0)
43 | goto orig;
44 |
45 | char * paths[] = {
46 | "share/locale",
47 | "gnome-platform/usr/share/locale",
48 | "usr/share/locale",
49 | "usr/share/locale-langpack",
50 | NULL
51 | };
52 | for(int i = 0; paths[i] != NULL; i++)
53 | {
54 | if (asprintf (&snap_path, "%s/%s", snap, paths[i]) < 0)
55 | continue;
56 |
57 | if (access (snap_path, F_OK) < 0)
58 | continue;
59 |
60 | /*
61 | * if the mo file exists for one language we assume it exists for them
62 | * all, or at least that we're not going to find it anywhere else. we
63 | * don't know at this point what locale the application is actually
64 | * going to use, so we can't look in any particular directory.
65 | */
66 | dir = opendir (snap_path);
67 | if (dir == NULL)
68 | continue;
69 |
70 | while ((ent = readdir (dir)) != NULL) {
71 | if (ent->d_name[0] == '.')
72 | continue;
73 |
74 | if (asprintf (&snap_locale_path,
75 | "%s/%s/LC_MESSAGES/%s.mo",
76 | snap_path,
77 | ent->d_name,
78 | domainname) < 0)
79 | continue;
80 |
81 | /* snap_locale_path has been allocated if we made it
82 | * this far, be sure it's freed before any goto
83 | * or continue
84 | */
85 |
86 | if (access (snap_locale_path, F_OK) == 0) {
87 | closedir (dir);
88 | free (snap_locale_path);
89 | snap_locale_path = NULL;
90 | goto ok;
91 | } else {
92 | free (snap_locale_path);
93 | snap_locale_path = NULL;
94 | continue;
95 | }
96 | }
97 |
98 | closedir (dir);
99 | free (snap_path);
100 | snap_path = NULL;
101 | free (snap_locale_path);
102 | snap_locale_path = NULL;
103 | }
104 | /*
105 | * we fell out of the loop, so we'll go to orig regardless - no need to
106 | * check for errors
107 | */
108 | goto orig;
109 |
110 | ok:
111 | ret = r_bindtextdomain (domainname, snap_path);
112 | goto out;
113 | orig:
114 | ret = r_bindtextdomain (domainname, dirname);
115 | goto out;
116 | out:
117 | free (snap_path);
118 | snap_path = NULL;
119 | return ret;
120 | }
121 |
--------------------------------------------------------------------------------
/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: desktop-helpers
2 | version: 1
3 | summary: Various technology desktop helpers for snapcraft
4 | description: |
5 | Note: We are currently in the process of moving most of the functionality of the
6 | desktop helpers to Snapcraft Extensions. The extensions are much easier to use
7 | and contain many improvements. Please read the documentation on snapping
8 | desktop applications to see what the best way is to create a snap for
9 | your application: https://forum.snapcraft.io/t/desktop-applications/13034
10 | .
11 | Helpers for gtk2, gtk3, qt4 and qt5 or gnome-platform and glib minimal launchers.
12 | It brings the necessary code and exports for binding and using those
13 | desktop technologies in a relocatable fashion, enabling binding with
14 | global desktop theme, icon theme, image caching, fonts, mimetype handlers
15 | application global menu and gsettings integration.
16 | It also brings basic ubuntu dependency packages.
17 | .
18 | Usage:
19 | 1. copy the part of the toolkit you need to your snapcraft.yaml file:
20 | - gtk2, gtk3, qt4 and qt5 corresponds to their respective toolkit
21 | main dependencies and default choices.
22 | - gnome-platform is similar to gtk3 without the extra depends, it's
23 | meant to be used with the gnome platform which already includes those.
24 | - glib-only enables to compile mime types and gsettings infos. If you
25 | added your own graphical drivers, it will link them as well.
26 | 2. prepend your command with "desktop-launch", like:
27 | commands: "desktop-launch foo" if foo is in $PATH. You can as well
28 | specify: "desktop-launch $SNAP/foo".
29 | 3. add needed plugs to your application:
30 | - for graphical application:
31 | plugs: [x11] or:
32 | [unity7] for appmenu, input methods, a11y integration. And/or:
33 | [desktop] for GNOME Shell/Plasma
34 | [wayland] for Wayland compositors
35 | See https://forum.snapcraft.io/t/the-desktop-interfaces/2042
36 | for details
37 | - if your application needs hw acceleration:
38 | plugs: [opengl]
39 | - for sound playback:
40 | plugs: [audio-playback]
41 | - for sound playback and recording:
42 | plugs: [audio-playback, audio-record]
43 | - accessing to user's home directory:
44 | plugs: [home]
45 | - read/write to gsettings:
46 | plugs: [gsettings]
47 | - if using "desktop" and need a11y or other input methods:
48 | plugs: [desktop-legacy]
49 | - use of the shared platform snap content, first define the plug:
50 | plugs:
51 | gnome-3-26-1604:
52 | interface: content
53 | target: gnome-platform
54 | default-provider: gnome-3-26-1604:gnome-3-26-1604
55 | and then make your apps use it:
56 | plugs: [gnome-3-26-1604]
57 | Note that an empty "gnome-platform" directory will be created for you
58 | in your snap.
59 |
60 | confinement: strict
61 |
62 | parts:
63 | desktop:
64 | plugin: nil
65 | gtk2:
66 | source: .
67 | source-subdir: gtk
68 | plugin: make
69 | make-parameters: ["FLAVOR=gtk2"]
70 | build-packages:
71 | - libgtk2.0-dev
72 | stage-packages:
73 | - libxkbcommon0 # XKB_CONFIG_ROOT
74 | - ttf-ubuntu-font-family
75 | - dmz-cursor-theme
76 | - light-themes
77 | - adwaita-icon-theme
78 | - gnome-themes-standard
79 | - shared-mime-info
80 | - libgtk2.0-0
81 | - libgdk-pixbuf2.0-0
82 | - libglib2.0-bin
83 | - libgtk2.0-bin
84 | - unity-gtk2-module
85 | - libappindicator1
86 | - locales-all
87 | - ibus-gtk
88 | - libibus-1.0-5
89 | gtk3:
90 | source: .
91 | source-subdir: gtk
92 | plugin: make
93 | make-parameters: ["FLAVOR=gtk3"]
94 | build-packages:
95 | - libgtk-3-dev
96 | stage-packages:
97 | - libxkbcommon0 # XKB_CONFIG_ROOT
98 | - ttf-ubuntu-font-family
99 | - dmz-cursor-theme
100 | - light-themes
101 | - adwaita-icon-theme
102 | - gnome-themes-standard
103 | - shared-mime-info
104 | - libgtk-3-0
105 | - libgdk-pixbuf2.0-0
106 | - libglib2.0-bin
107 | - libgtk-3-bin
108 | - unity-gtk3-module
109 | - libappindicator3-1
110 | - locales-all
111 | - xdg-user-dirs
112 | - ibus-gtk3
113 | - libibus-1.0-5
114 | qt4:
115 | source: .
116 | source-subdir: qt
117 | plugin: make
118 | make-parameters: ["FLAVOR=qt4"]
119 | build-packages:
120 | - libqt4-dev
121 | - dpkg-dev
122 | stage-packages:
123 | - libxkbcommon0
124 | - ttf-ubuntu-font-family
125 | - dmz-cursor-theme
126 | - light-themes
127 | - adwaita-icon-theme
128 | - gnome-themes-standard
129 | - shared-mime-info
130 | - libqtgui4
131 | - libgdk-pixbuf2.0-0
132 | - libqt4-svg # for loading icon themes which are svg
133 | - appmenu-qt
134 | - locales-all
135 | - sni-qt
136 | qt5:
137 | source: .
138 | source-subdir: qt
139 | plugin: make
140 | make-parameters: ["FLAVOR=qt5"]
141 | build-packages:
142 | - qtbase5-dev
143 | - dpkg-dev
144 | stage-packages:
145 | - libxkbcommon0
146 | - ttf-ubuntu-font-family
147 | - dmz-cursor-theme
148 | - light-themes
149 | - adwaita-icon-theme
150 | - gnome-themes-standard
151 | - shared-mime-info
152 | - libqt5gui5
153 | - libgdk-pixbuf2.0-0
154 | - libqt5svg5 # for loading icon themes which are svg
155 | - try: [appmenu-qt5] # not available on core18
156 | - locales-all
157 | glib-only:
158 | source: .
159 | source-subdir: glib-only
160 | plugin: make
161 | build-packages:
162 | - libglib2.0-dev
163 | stage-packages:
164 | - libglib2.0-bin
165 | desktop-gtk2:
166 | source: .
167 | source-subdir: gtk
168 | plugin: make
169 | make-parameters: ["FLAVOR=gtk2"]
170 | build-packages:
171 | - build-essential
172 | - libgtk2.0-dev
173 | stage-packages:
174 | - libxkbcommon0 # XKB_CONFIG_ROOT
175 | - ttf-ubuntu-font-family
176 | - dmz-cursor-theme
177 | - light-themes
178 | - adwaita-icon-theme
179 | - gnome-themes-standard
180 | - shared-mime-info
181 | - libgtk2.0-0
182 | - libgdk-pixbuf2.0-0
183 | - libglib2.0-bin
184 | - libgtk2.0-bin
185 | - unity-gtk2-module
186 | - locales-all
187 | - libappindicator1
188 | - xdg-user-dirs
189 | - ibus-gtk
190 | - libibus-1.0-5
191 | desktop-gtk3:
192 | source: .
193 | source-subdir: gtk
194 | plugin: make
195 | make-parameters: ["FLAVOR=gtk3"]
196 | build-packages:
197 | - build-essential
198 | - libgtk-3-dev
199 | stage-packages:
200 | - libxkbcommon0 # XKB_CONFIG_ROOT
201 | - ttf-ubuntu-font-family
202 | - dmz-cursor-theme
203 | - light-themes
204 | - adwaita-icon-theme
205 | - gnome-themes-standard
206 | - shared-mime-info
207 | - libgtk-3-0
208 | - libgdk-pixbuf2.0-0
209 | - libglib2.0-bin
210 | - libgtk-3-bin
211 | - unity-gtk3-module
212 | - libappindicator3-1
213 | - locales-all
214 | - xdg-user-dirs
215 | - ibus-gtk3
216 | - libibus-1.0-5
217 | - fcitx-frontend-gtk3
218 | desktop-qt4:
219 | source: .
220 | source-subdir: qt
221 | plugin: make
222 | make-parameters: ["FLAVOR=qt4"]
223 | build-packages:
224 | - build-essential
225 | - libqt4-dev
226 | - dpkg-dev
227 | stage-packages:
228 | - libxkbcommon0
229 | - ttf-ubuntu-font-family
230 | - dmz-cursor-theme
231 | - light-themes
232 | - adwaita-icon-theme
233 | - gnome-themes-standard
234 | - shared-mime-info
235 | - libqtgui4
236 | - libgdk-pixbuf2.0-0
237 | - libqt4-svg # for loading icon themes which are svg
238 | - appmenu-qt
239 | - locales-all
240 | - sni-qt
241 | - xdg-user-dirs
242 | desktop-qt5:
243 | source: .
244 | source-subdir: qt
245 | plugin: make
246 | make-parameters: ["FLAVOR=qt5"]
247 | build-packages:
248 | - build-essential
249 | - qtbase5-dev
250 | - dpkg-dev
251 | stage-packages:
252 | - libxkbcommon0
253 | - ttf-ubuntu-font-family
254 | - dmz-cursor-theme
255 | - light-themes
256 | - adwaita-icon-theme
257 | - gnome-themes-standard
258 | - shared-mime-info
259 | - libqt5gui5
260 | - libgdk-pixbuf2.0-0
261 | - libqt5svg5 # for loading icon themes which are svg
262 | - try: [appmenu-qt5] # not available on core18
263 | - locales-all
264 | - xdg-user-dirs
265 | - fcitx-frontend-qt5
266 | desktop-glib-only:
267 | source: .
268 | source-subdir: glib-only
269 | plugin: make
270 | build-packages:
271 | - libglib2.0-dev
272 | stage-packages:
273 | - libglib2.0-bin
274 | desktop-gnome-platform:
275 | source: .
276 | source-subdir: gtk
277 | plugin: make
278 | make-parameters: ["FLAVOR=gtk3"]
279 | build-packages:
280 | - gcc
281 | override-build: |
282 | snapcraftctl build
283 | mkdir -pv $SNAPCRAFT_PART_INSTALL/gnome-platform
284 |
--------------------------------------------------------------------------------
/demos/qt5/src/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2015 The Qt Company Ltd.
4 | ** Contact: http://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** You may use this file under the terms of the BSD license as follows:
10 | **
11 | ** "Redistribution and use in source and binary forms, with or without
12 | ** modification, are permitted provided that the following conditions are
13 | ** met:
14 | ** * Redistributions of source code must retain the above copyright
15 | ** notice, this list of conditions and the following disclaimer.
16 | ** * Redistributions in binary form must reproduce the above copyright
17 | ** notice, this list of conditions and the following disclaimer in
18 | ** the documentation and/or other materials provided with the
19 | ** distribution.
20 | ** * Neither the name of The Qt Company Ltd nor the names of its
21 | ** contributors may be used to endorse or promote products derived
22 | ** from this software without specific prior written permission.
23 | **
24 | **
25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 | **
37 | ** $QT_END_LICENSE$
38 | **
39 | ****************************************************************************/
40 |
41 | //! [0]
42 | #include
43 |
44 | #include "mainwindow.h"
45 | //! [0]
46 |
47 | //! [1]
48 | MainWindow::MainWindow()
49 | //! [1] //! [2]
50 | {
51 | textEdit = new QPlainTextEdit;
52 | setCentralWidget(textEdit);
53 |
54 | createActions();
55 | createMenus();
56 | createToolBars();
57 | createStatusBar();
58 |
59 | readSettings();
60 |
61 | connect(textEdit->document(), SIGNAL(contentsChanged()),
62 | this, SLOT(documentWasModified()));
63 |
64 | setCurrentFile("");
65 | setUnifiedTitleAndToolBarOnMac(true);
66 | }
67 | //! [2]
68 |
69 | //! [3]
70 | void MainWindow::closeEvent(QCloseEvent *event)
71 | //! [3] //! [4]
72 | {
73 | if (maybeSave()) {
74 | writeSettings();
75 | event->accept();
76 | } else {
77 | event->ignore();
78 | }
79 | }
80 | //! [4]
81 |
82 | //! [5]
83 | void MainWindow::newFile()
84 | //! [5] //! [6]
85 | {
86 | if (maybeSave()) {
87 | textEdit->clear();
88 | setCurrentFile("");
89 | }
90 | }
91 | //! [6]
92 |
93 | //! [7]
94 | void MainWindow::open()
95 | //! [7] //! [8]
96 | {
97 | if (maybeSave()) {
98 | QString fileName = QFileDialog::getOpenFileName(this);
99 | if (!fileName.isEmpty())
100 | loadFile(fileName);
101 | }
102 | }
103 | //! [8]
104 |
105 | //! [9]
106 | bool MainWindow::save()
107 | //! [9] //! [10]
108 | {
109 | if (curFile.isEmpty()) {
110 | return saveAs();
111 | } else {
112 | return saveFile(curFile);
113 | }
114 | }
115 | //! [10]
116 |
117 | //! [11]
118 | bool MainWindow::saveAs()
119 | //! [11] //! [12]
120 | {
121 | QFileDialog dialog(this);
122 | dialog.setWindowModality(Qt::WindowModal);
123 | dialog.setAcceptMode(QFileDialog::AcceptSave);
124 | QStringList files;
125 | if (dialog.exec())
126 | files = dialog.selectedFiles();
127 | else
128 | return false;
129 |
130 | return saveFile(files.at(0));
131 | }
132 | //! [12]
133 |
134 | //! [13]
135 | void MainWindow::about()
136 | //! [13] //! [14]
137 | {
138 | QMessageBox::about(this, tr("About Application"),
139 | tr("The Application example demonstrates how to "
140 | "write modern GUI applications using Qt, with a menu bar, "
141 | "toolbars, and a status bar."));
142 | }
143 | //! [14]
144 |
145 | //! [15]
146 | void MainWindow::documentWasModified()
147 | //! [15] //! [16]
148 | {
149 | setWindowModified(textEdit->document()->isModified());
150 | }
151 | //! [16]
152 |
153 | //! [17]
154 | void MainWindow::createActions()
155 | //! [17] //! [18]
156 | {
157 | newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
158 | newAct->setShortcuts(QKeySequence::New);
159 | newAct->setStatusTip(tr("Create a new file"));
160 | connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
161 |
162 | //! [19]
163 | openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
164 | openAct->setShortcuts(QKeySequence::Open);
165 | openAct->setStatusTip(tr("Open an existing file"));
166 | connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
167 | //! [18] //! [19]
168 |
169 | saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this);
170 | saveAct->setShortcuts(QKeySequence::Save);
171 | saveAct->setStatusTip(tr("Save the document to disk"));
172 | connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
173 |
174 | saveAsAct = new QAction(tr("Save &As..."), this);
175 | saveAsAct->setShortcuts(QKeySequence::SaveAs);
176 | saveAsAct->setStatusTip(tr("Save the document under a new name"));
177 | connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
178 |
179 | //! [20]
180 | exitAct = new QAction(tr("E&xit"), this);
181 | exitAct->setShortcuts(QKeySequence::Quit);
182 | //! [20]
183 | exitAct->setStatusTip(tr("Exit the application"));
184 | connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
185 |
186 | //! [21]
187 | cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);
188 | //! [21]
189 | cutAct->setShortcuts(QKeySequence::Cut);
190 | cutAct->setStatusTip(tr("Cut the current selection's contents to the "
191 | "clipboard"));
192 | connect(cutAct, SIGNAL(triggered()), textEdit, SLOT(cut()));
193 |
194 | copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this);
195 | copyAct->setShortcuts(QKeySequence::Copy);
196 | copyAct->setStatusTip(tr("Copy the current selection's contents to the "
197 | "clipboard"));
198 | connect(copyAct, SIGNAL(triggered()), textEdit, SLOT(copy()));
199 |
200 | pasteAct = new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this);
201 | pasteAct->setShortcuts(QKeySequence::Paste);
202 | pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
203 | "selection"));
204 | connect(pasteAct, SIGNAL(triggered()), textEdit, SLOT(paste()));
205 |
206 | aboutAct = new QAction(tr("&About"), this);
207 | aboutAct->setStatusTip(tr("Show the application's About box"));
208 | connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
209 |
210 | //! [22]
211 | aboutQtAct = new QAction(tr("About &Qt"), this);
212 | aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
213 | connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
214 | //! [22]
215 |
216 | //! [23]
217 | cutAct->setEnabled(false);
218 | //! [23] //! [24]
219 | copyAct->setEnabled(false);
220 | connect(textEdit, SIGNAL(copyAvailable(bool)),
221 | cutAct, SLOT(setEnabled(bool)));
222 | connect(textEdit, SIGNAL(copyAvailable(bool)),
223 | copyAct, SLOT(setEnabled(bool)));
224 | }
225 | //! [24]
226 |
227 | //! [25] //! [26]
228 | void MainWindow::createMenus()
229 | //! [25] //! [27]
230 | {
231 | fileMenu = menuBar()->addMenu(tr("&File"));
232 | fileMenu->addAction(newAct);
233 | //! [28]
234 | fileMenu->addAction(openAct);
235 | //! [28]
236 | fileMenu->addAction(saveAct);
237 | //! [26]
238 | fileMenu->addAction(saveAsAct);
239 | fileMenu->addSeparator();
240 | fileMenu->addAction(exitAct);
241 |
242 | editMenu = menuBar()->addMenu(tr("&Edit"));
243 | editMenu->addAction(cutAct);
244 | editMenu->addAction(copyAct);
245 | editMenu->addAction(pasteAct);
246 |
247 | menuBar()->addSeparator();
248 |
249 | helpMenu = menuBar()->addMenu(tr("&Help"));
250 | helpMenu->addAction(aboutAct);
251 | helpMenu->addAction(aboutQtAct);
252 | }
253 | //! [27]
254 |
255 | //! [29] //! [30]
256 | void MainWindow::createToolBars()
257 | {
258 | fileToolBar = addToolBar(tr("File"));
259 | fileToolBar->addAction(newAct);
260 | //! [29] //! [31]
261 | fileToolBar->addAction(openAct);
262 | //! [31]
263 | fileToolBar->addAction(saveAct);
264 |
265 | editToolBar = addToolBar(tr("Edit"));
266 | editToolBar->addAction(cutAct);
267 | editToolBar->addAction(copyAct);
268 | editToolBar->addAction(pasteAct);
269 | }
270 | //! [30]
271 |
272 | //! [32]
273 | void MainWindow::createStatusBar()
274 | //! [32] //! [33]
275 | {
276 | statusBar()->showMessage(tr("Ready"));
277 | }
278 | //! [33]
279 |
280 | //! [34] //! [35]
281 | void MainWindow::readSettings()
282 | //! [34] //! [36]
283 | {
284 | QSettings settings("QtProject", "Application Example");
285 | QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
286 | QSize size = settings.value("size", QSize(400, 400)).toSize();
287 | resize(size);
288 | move(pos);
289 | }
290 | //! [35] //! [36]
291 |
292 | //! [37] //! [38]
293 | void MainWindow::writeSettings()
294 | //! [37] //! [39]
295 | {
296 | QSettings settings("QtProject", "Application Example");
297 | settings.setValue("pos", pos());
298 | settings.setValue("size", size());
299 | }
300 | //! [38] //! [39]
301 |
302 | //! [40]
303 | bool MainWindow::maybeSave()
304 | //! [40] //! [41]
305 | {
306 | if (textEdit->document()->isModified()) {
307 | QMessageBox::StandardButton ret;
308 | ret = QMessageBox::warning(this, tr("Application"),
309 | tr("The document has been modified.\n"
310 | "Do you want to save your changes?"),
311 | QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
312 | if (ret == QMessageBox::Save)
313 | return save();
314 | else if (ret == QMessageBox::Cancel)
315 | return false;
316 | }
317 | return true;
318 | }
319 | //! [41]
320 |
321 | //! [42]
322 | void MainWindow::loadFile(const QString &fileName)
323 | //! [42] //! [43]
324 | {
325 | QFile file(fileName);
326 | if (!file.open(QFile::ReadOnly | QFile::Text)) {
327 | QMessageBox::warning(this, tr("Application"),
328 | tr("Cannot read file %1:\n%2.")
329 | .arg(fileName)
330 | .arg(file.errorString()));
331 | return;
332 | }
333 |
334 | QTextStream in(&file);
335 | #ifndef QT_NO_CURSOR
336 | QApplication::setOverrideCursor(Qt::WaitCursor);
337 | #endif
338 | textEdit->setPlainText(in.readAll());
339 | #ifndef QT_NO_CURSOR
340 | QApplication::restoreOverrideCursor();
341 | #endif
342 |
343 | setCurrentFile(fileName);
344 | statusBar()->showMessage(tr("File loaded"), 2000);
345 | }
346 | //! [43]
347 |
348 | //! [44]
349 | bool MainWindow::saveFile(const QString &fileName)
350 | //! [44] //! [45]
351 | {
352 | QFile file(fileName);
353 | if (!file.open(QFile::WriteOnly | QFile::Text)) {
354 | QMessageBox::warning(this, tr("Application"),
355 | tr("Cannot write file %1:\n%2.")
356 | .arg(fileName)
357 | .arg(file.errorString()));
358 | return false;
359 | }
360 |
361 | QTextStream out(&file);
362 | #ifndef QT_NO_CURSOR
363 | QApplication::setOverrideCursor(Qt::WaitCursor);
364 | #endif
365 | out << textEdit->toPlainText();
366 | #ifndef QT_NO_CURSOR
367 | QApplication::restoreOverrideCursor();
368 | #endif
369 |
370 | setCurrentFile(fileName);
371 | statusBar()->showMessage(tr("File saved"), 2000);
372 | return true;
373 | }
374 | //! [45]
375 |
376 | //! [46]
377 | void MainWindow::setCurrentFile(const QString &fileName)
378 | //! [46] //! [47]
379 | {
380 | curFile = fileName;
381 | textEdit->document()->setModified(false);
382 | setWindowModified(false);
383 |
384 | QString shownName = curFile;
385 | if (curFile.isEmpty())
386 | shownName = "untitled.txt";
387 | setWindowFilePath(shownName);
388 | }
389 | //! [47]
390 |
391 | //! [48]
392 | QString MainWindow::strippedName(const QString &fullFileName)
393 | //! [48] //! [49]
394 | {
395 | return QFileInfo(fullFileName).fileName();
396 | }
397 | //! [49]
398 |
--------------------------------------------------------------------------------
/common/desktop-exports:
--------------------------------------------------------------------------------
1 | ###############################################
2 | # Launcher common exports for any desktop app #
3 | ###############################################
4 |
5 | function prepend_dir() {
6 | local var="$1"
7 | local dir="$2"
8 | if [ -d "$dir" ]; then
9 | eval "export $var=\"\$dir\${$var:+:\$$var}\""
10 | fi
11 | }
12 |
13 | function append_dir() {
14 | local var="$1"
15 | local dir="$2"
16 | if [ -d "$dir" ]; then
17 | eval "export $var=\"\${$var:+\$$var:}\$dir\""
18 | fi
19 | }
20 |
21 | function can_open_file() {
22 | return `head -c0 "$1" &> /dev/null`;
23 | }
24 |
25 | function update_xdg_dirs_values() {
26 | local save_initial_values=false
27 | local XDG_DIRS="DOCUMENTS DESKTOP DOWNLOAD MUSIC PICTURES VIDEOS PUBLICSHARE TEMPLATES"
28 | unset XDG_SPECIAL_DIRS_PATHS
29 |
30 | if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" ]; then
31 | source "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs"
32 | fi
33 |
34 | if [ -z ${XDG_SPECIAL_DIRS+x} ]; then
35 | save_initial_values=true
36 | fi
37 |
38 | for d in $XDG_DIRS; do
39 | var="XDG_${d}_DIR"
40 | value="$(eval echo $(echo \$${var}))"
41 |
42 | if [ "$save_initial_values" = true ]; then
43 | XDG_SPECIAL_DIRS+=("$var")
44 | XDG_SPECIAL_DIRS_INITIAL_PATHS+=("$value")
45 | fi
46 |
47 | XDG_SPECIAL_DIRS_PATHS+=("$value")
48 | done
49 | }
50 |
51 | function is_subpath() {
52 | dir=$(realpath $1)
53 | parent=$(realpath $2)
54 | [ "${dir##$parent/}" != "$dir" ] && return 0 || return 1
55 | }
56 |
57 | WITH_RUNTIME=no
58 | if [ -z "$RUNTIME" ]; then
59 | RUNTIME=$SNAP
60 | else
61 | # add general paths not added by snapcraft due to runtime snap
62 | append_dir LD_LIBRARY_PATH $RUNTIME/lib/$ARCH
63 | append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib
64 | append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH
65 | append_dir PATH $RUNTIME/usr/bin
66 | WITH_RUNTIME=yes
67 | fi
68 |
69 | # XKB config
70 | export XKB_CONFIG_ROOT=$RUNTIME/usr/share/X11/xkb
71 |
72 | # Give XOpenIM a chance to locate locale data.
73 | # This is required for text input to work in SDL2 games.
74 | export XLOCALEDIR=$RUNTIME/usr/share/X11/locale
75 |
76 | # Set XCursors path
77 | export XCURSOR_PATH=$RUNTIME/usr/share/icons
78 | prepend_dir XCURSOR_PATH $SNAP/data-dir/icons
79 |
80 | # Mesa Libs for OpenGL support
81 | append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH/mesa
82 | append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH/mesa-egl
83 |
84 | # Tell libGL and libva where to find the drivers
85 | export LIBGL_DRIVERS_PATH=$RUNTIME/usr/lib/$ARCH/dri
86 | append_dir LD_LIBRARY_PATH $LIBGL_DRIVERS_PATH
87 | export LIBVA_DRIVERS_PATH=$RUNTIME/usr/lib/$ARCH/dri
88 |
89 | # Set where the VDPAU drivers are located
90 | export VDPAU_DRIVER_PATH="/usr/lib/$ARCH/vdpau/"
91 | if [ -e "/var/lib/snapd/lib/gl/vdpau/libvdpau_nvidia.so" ]; then
92 | export VDPAU_DRIVER_PATH="/var/lib/snapd/lib/gl/vdpau"
93 | # Prevent picking VA-API (Intel/AMD) over NVIDIA VDPAU; on PRIME systems for example
94 | unset LIBVA_DRIVERS_PATH
95 | fi
96 |
97 | # Unity7 export (workaround for https://launchpad.net/bugs/1638405)
98 | append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH/libunity
99 |
100 | # Pulseaudio export
101 | append_dir LD_LIBRARY_PATH $RUNTIME/usr/lib/$ARCH/pulseaudio
102 |
103 | # EGL vendor files on glvnd enabled systems
104 | [ -d /var/lib/snapd/lib/glvnd/egl_vendor.d ] && \
105 | prepend_dir __EGL_VENDOR_LIBRARY_DIRS /var/lib/snapd/lib/glvnd/egl_vendor.d
106 |
107 | # EGL vendor files
108 | append_dir __EGL_VENDOR_LIBRARY_DIRS $RUNTIME/etc/glvnd/egl_vendor.d
109 | append_dir __EGL_VENDOR_LIBRARY_DIRS $RUNTIME/usr/share/glvnd/egl_vendor.d
110 |
111 | # Tell GStreamer where to find its plugins
112 | export GST_PLUGIN_PATH=$SNAP/usr/lib/$ARCH/gstreamer-1.0
113 | export GST_PLUGIN_SYSTEM_PATH=$RUNTIME/usr/lib/$ARCH/gstreamer-1.0
114 | # gst plugin scanner doesn't install in the correct path: https://github.com/ubuntu/snapcraft-desktop-helpers/issues/43
115 | export GST_PLUGIN_SCANNER=$RUNTIME/usr/lib/$ARCH/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner
116 |
117 | # XDG Config
118 | [ "$WITH_RUNTIME" = yes ] && prepend_dir XDG_CONFIG_DIRS $RUNTIME/etc/xdg
119 | prepend_dir XDG_CONFIG_DIRS $SNAP/etc/xdg
120 |
121 | # Define snaps' own data dir
122 | [ "$WITH_RUNTIME" = yes ] && prepend_dir XDG_DATA_DIRS $RUNTIME/usr/share
123 | prepend_dir XDG_DATA_DIRS $SNAP/usr/share
124 | prepend_dir XDG_DATA_DIRS $SNAP/share
125 | prepend_dir XDG_DATA_DIRS $SNAP/data-dir
126 | prepend_dir XDG_DATA_DIRS $SNAP_USER_DATA
127 |
128 | # Set XDG_DATA_HOME to local path
129 | export XDG_DATA_HOME=$SNAP_USER_DATA/.local/share
130 | ensure_dir_exists $XDG_DATA_HOME -m 700
131 |
132 | # Workaround for GLib < 2.53.2 not searching for schemas in $XDG_DATA_HOME:
133 | # https://bugzilla.gnome.org/show_bug.cgi?id=741335
134 | prepend_dir XDG_DATA_DIRS $XDG_DATA_HOME
135 |
136 | # Set cache folder to local path
137 | export XDG_CACHE_HOME=$SNAP_USER_COMMON/.cache
138 | if [[ -d $SNAP_USER_DATA/.cache && ! -e $XDG_CACHE_HOME ]]; then
139 | # the .cache directory used to be stored under $SNAP_USER_DATA, migrate it
140 | mv $SNAP_USER_DATA/.cache $SNAP_USER_COMMON/
141 | fi
142 | ensure_dir_exists $XDG_CACHE_HOME -m 700
143 |
144 | # Create $XDG_RUNTIME_DIR if not exists (to be removed when LP: #1656340 is fixed)
145 | ensure_dir_exists $XDG_RUNTIME_DIR -m 700
146 |
147 | # Ensure the app finds locale definitions (requires locales-all to be installed)
148 | append_dir LOCPATH $RUNTIME/usr/lib/locale
149 |
150 | # If any, keep track of where XDG dirs were so we can potentially migrate the content later
151 | update_xdg_dirs_values
152 |
153 | # Setup user-dirs.* or run xdg-user-dirs-update if needed
154 | needs_xdg_update=false
155 | needs_xdg_reload=false
156 | needs_xdg_links=false
157 |
158 | if [ "$HOME" != "$SNAP_USER_DATA" ] && ! is_subpath "$XDG_CONFIG_HOME" "$HOME"; then
159 | for f in user-dirs.dirs user-dirs.locale; do
160 | if [ -f "$HOME/.config/$f" ]; then
161 | mv "$HOME/.config/$f" "$XDG_CONFIG_HOME"
162 | needs_xdg_reload=true
163 | fi
164 | done
165 | fi
166 |
167 | if can_open_file "$REALHOME/.config/user-dirs.dirs"; then
168 | # shellcheck disable=SC2154
169 | if [ "$needs_update" = true ] || [ "$needs_xdg_reload" = true ]; then
170 | sed "/^#/!s#\$HOME#${REALHOME}#g" "$REALHOME/.config/user-dirs.dirs" > "$XDG_CONFIG_HOME/user-dirs.dirs"
171 | md5sum < "$REALHOME/.config/user-dirs.dirs" > "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum"
172 | # It's possible user-dirs.dirs exists when user-dirs.locale doesn't. This
173 | # simply means the user opted to never ask to translate their user dirs
174 | if can_open_file "$REALHOME/.config/user-dirs.locale"; then
175 | cp -a "$REALHOME/.config/user-dirs.locale" "$XDG_CONFIG_HOME"
176 | md5sum < "$REALHOME/.config/user-dirs.locale" > "$XDG_CONFIG_HOME/user-dirs.locale.md5sum"
177 | elif [ -f "$XDG_CONFIG_HOME/user-dirs.locale.md5sum" ]; then
178 | rm "$XDG_CONFIG_HOME/user-dirs.locale.md5sum"
179 | fi
180 | needs_xdg_reload=true
181 | fi
182 | else
183 | needs_xdg_update=true
184 | needs_xdg_links=true
185 | fi
186 |
187 | if [ $needs_xdg_reload = true ]; then
188 | update_xdg_dirs_values
189 | needs_xdg_reload=false
190 | fi
191 |
192 | # Check if we can actually read the contents of each xdg dir
193 | for ((i = 0; i < ${#XDG_SPECIAL_DIRS_PATHS[@]}; i++)); do
194 | if ! can_open_file "${XDG_SPECIAL_DIRS_PATHS[$i]}"; then
195 | needs_xdg_update=true
196 | needs_xdg_links=true
197 | break
198 | fi
199 | done
200 |
201 | # If needs XDG update and xdg-user-dirs-update exists in $PATH, run it
202 | if [ $needs_xdg_update = true ] && command -v xdg-user-dirs-update >/dev/null; then
203 | xdg-user-dirs-update
204 | update_xdg_dirs_values
205 | fi
206 |
207 | # Create links for user-dirs.dirs
208 | if [ $needs_xdg_links = true ]; then
209 | for ((i = 0; i < ${#XDG_SPECIAL_DIRS_PATHS[@]}; i++)); do
210 | b=$(realpath "${XDG_SPECIAL_DIRS_PATHS[$i]}" --relative-to="$HOME")
211 | if [[ "$b" != "." && -e $REALHOME/$b ]]; then
212 | [ -d $HOME/$b ] && rmdir $HOME/$b 2> /dev/null
213 | [ ! -e $HOME/$b ] && ln -s $REALHOME/$b $HOME/$b
214 | fi
215 | done
216 | else
217 | # If we aren't creating new links, check if we have content saved in old locations and move it
218 | for ((i = 0; i < ${#XDG_SPECIAL_DIRS[@]}; i++)); do
219 | old="${XDG_SPECIAL_DIRS_INITIAL_PATHS[$i]}"
220 | new="${XDG_SPECIAL_DIRS_PATHS[$i]}"
221 | if [ -L "$old" ] && [ -d "$new" ] && [ `readlink "$old" 2>/dev/null` != "$new" ] &&
222 | (is_subpath "$old" "$SNAP_USER_DATA" || is_subpath "$old" "$SNAP_USER_COMMON"); then
223 | mv -vn "$old"/* "$new"/ 2>/dev/null
224 | elif [ -d "$old" ] && [ -d "$new" ] && [ "$old" != "$new" ] &&
225 | (is_subpath "$old" "$SNAP_USER_DATA" || is_subpath "$old" "$SNAP_USER_COMMON"); then
226 | mv -vn "$old"/* "$new"/ 2>/dev/null
227 | fi
228 | done
229 | fi
230 |
231 | # If detect wayland server socket, then set environment so applications prefer
232 | # wayland, and setup compat symlink (until we use user mounts. Remember,
233 | # XDG_RUNTIME_DIR is /run/user//snap.$SNAP so look in the parent directory
234 | # for the socket. For details:
235 | # https://forum.snapcraft.io/t/wayland-dconf-and-xdg-runtime-dir/186/10
236 | # Applications that don't support wayland natively may define DISABLE_WAYLAND
237 | # (to any non-empty value) to skip that logic entirely.
238 | wayland_available=false
239 | if [[ -n "$XDG_RUNTIME_DIR" && -z "$DISABLE_WAYLAND" ]]; then
240 | wdisplay="wayland-0"
241 | if [ -n "$WAYLAND_DISPLAY" ]; then
242 | wdisplay="$WAYLAND_DISPLAY"
243 | fi
244 | wayland_sockpath="$XDG_RUNTIME_DIR/../$wdisplay"
245 | wayland_snappath="$XDG_RUNTIME_DIR/$wdisplay"
246 | if [ -S "$wayland_sockpath" ]; then
247 | # if running under wayland, use it
248 | #export WAYLAND_DEBUG=1
249 | wayland_available=true
250 | # create the compat symlink for now
251 | if [ ! -e "$wayland_snappath" ]; then
252 | ln -s "$wayland_sockpath" "$wayland_snappath"
253 | fi
254 | fi
255 | fi
256 |
257 | # Make PulseAudio socket available inside the snap-specific $XDG_RUNTIME_DIR
258 | if [ -n "$XDG_RUNTIME_DIR" ]; then
259 | pulsenative="pulse/native"
260 | pulseaudio_sockpath="$XDG_RUNTIME_DIR/../$pulsenative"
261 | if [ -S "$pulseaudio_sockpath" ]; then
262 | export PULSE_SERVER="unix:${pulseaudio_sockpath}"
263 | fi
264 | fi
265 |
266 | # GI repository
267 | [ "$WITH_RUNTIME" = yes ] && prepend_dir GI_TYPELIB_PATH $RUNTIME/usr/lib/$ARCH/girepository-1.0
268 | [ "$WITH_RUNTIME" = yes ] && prepend_dir GI_TYPELIB_PATH $RUNTIME/usr/lib/girepository-1.0
269 | prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/$ARCH/girepository-1.0
270 | prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/girepository-1.0
271 | prepend_dir GI_TYPELIB_PATH $SNAP/usr/lib/gjs/girepository-1.0
272 |
273 | # Keep an array of data dirs, for looping through them
274 | IFS=':' read -r -a data_dirs_array <<< "$XDG_DATA_DIRS"
275 |
276 | # Font Config and themes
277 | export FONTCONFIG_PATH=$RUNTIME/etc/fonts
278 | export FONTCONFIG_FILE=$RUNTIME/etc/fonts/fonts.conf
279 |
280 | function make_user_fontconfig {
281 | echo ""
282 | if [ -d $REALHOME/.local/share/fonts ]; then
283 | echo " $REALHOME/.local/share/fonts"
284 | fi
285 | if [ -d $REALHOME/.fonts ]; then
286 | echo " $REALHOME/.fonts"
287 | fi
288 | for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do
289 | if [ -d "${data_dirs_array[$i]}/fonts" ]; then
290 | echo " ${data_dirs_array[$i]}/fonts"
291 | fi
292 | done
293 | # fix font render for modified fonts, that discussed on Snapcraft Forum:
294 | # https://forum.snapcraft.io/t/snap-package-cannot-read-fonts-conf/16657
295 | echo ' /etc/fonts/conf.d'
296 | echo ' conf.d'
297 |
298 | # We need to include this default cachedir first so that caching
299 | # works: without it, fontconfig will try to write to the real user home
300 | # cachedir and be blocked by AppArmor.
301 | echo ' fontconfig'
302 | if [ -d $REALHOME/.cache/fontconfig ]; then
303 | echo " $REALHOME/.cache/fontconfig"
304 | fi
305 | echo ""
306 | }
307 |
308 | if [ $needs_update = true ]; then
309 | rm -rf $XDG_DATA_HOME/{fontconfig,fonts,fonts-*,themes,.themes}
310 |
311 | # This fontconfig fragment is installed in a location that is
312 | # included by the system fontconfig configuration: namely the
313 | # etc/fonts/conf.d/50-user.conf file.
314 | ensure_dir_exists $XDG_CONFIG_HOME/fontconfig
315 | async_exec make_user_fontconfig > $XDG_CONFIG_HOME/fontconfig/fonts.conf
316 |
317 | # the themes symlink are needed for GTK 3.18 when the prefix isn't changed
318 | # GTK 3.20 looks into XDG_DATA_DIR which has connected themes.
319 | if [ -d $SNAP/data-dir/themes ]; then
320 | ln -sf $SNAP/data-dir/themes $XDG_DATA_HOME
321 | ln -sfn $SNAP/data-dir/themes $SNAP_USER_DATA/.themes
322 | else
323 | ln -sf $RUNTIME/usr/share/themes $XDG_DATA_HOME
324 | ln -sfn $RUNTIME/usr/share/themes $SNAP_USER_DATA/.themes
325 | fi
326 | fi
327 |
328 | # Build mime.cache
329 | # needed for gtk and qt icon
330 | if [ $needs_update = true ]; then
331 | rm -rf $XDG_DATA_HOME/mime
332 | if [ ! -f $RUNTIME/usr/share/mime/mime.cache ]; then
333 | if command -v update-mime-database >/dev/null; then
334 | cp --preserve=timestamps -dR $RUNTIME/usr/share/mime $XDG_DATA_HOME
335 | async_exec update-mime-database $XDG_DATA_HOME/mime
336 | fi
337 | fi
338 | fi
339 |
340 | # Gio modules and cache (including gsettings module)
341 | export GIO_MODULE_DIR=$XDG_CACHE_HOME/gio-modules
342 | function compile_giomodules {
343 | if [ -f $1/glib-2.0/gio-querymodules ]; then
344 | rm -rf $GIO_MODULE_DIR
345 | ensure_dir_exists $GIO_MODULE_DIR
346 | ln -s $1/gio/modules/*.so $GIO_MODULE_DIR
347 | $1/glib-2.0/gio-querymodules $GIO_MODULE_DIR
348 | fi
349 | }
350 | if [ $needs_update = true ]; then
351 | async_exec compile_giomodules $RUNTIME/usr/lib/$ARCH
352 | fi
353 |
354 | # Setup compiled gsettings schema
355 | GS_SCHEMA_DIR=$XDG_DATA_HOME/glib-2.0/schemas
356 | function compile_schemas {
357 | if [ -f "$1" ]; then
358 | rm -rf $GS_SCHEMA_DIR
359 | ensure_dir_exists $GS_SCHEMA_DIR
360 | for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do
361 | schema_dir="${data_dirs_array[$i]}/glib-2.0/schemas"
362 | if [ -f "$schema_dir/gschemas.compiled" ]; then
363 | # This directory already has compiled schemas
364 | continue
365 | fi
366 | if [ -n "$(ls -A $schema_dir/*.xml 2>/dev/null)" ]; then
367 | ln -s $schema_dir/*.xml $GS_SCHEMA_DIR
368 | fi
369 | if [ -n "$(ls -A $schema_dir/*.override 2>/dev/null)" ]; then
370 | ln -s $schema_dir/*.override $GS_SCHEMA_DIR
371 | fi
372 | done
373 | # Only compile schemas if we copied anyting
374 | if [ -n "$(ls -A $GS_SCHEMA_DIR/*.xml $GS_SCHEMA_DIR/*.override 2>/dev/null)" ]; then
375 | "$1" $GS_SCHEMA_DIR
376 | fi
377 | fi
378 | }
379 | if [ $needs_update = true ]; then
380 | async_exec compile_schemas $RUNTIME/usr/lib/$ARCH/glib-2.0/glib-compile-schemas
381 | fi
382 |
383 | # Enable gsettings user changes
384 | # symlink the dconf file if home plug is connected for read
385 | DCONF_DEST_USER_DIR=$SNAP_USER_DATA/.config/dconf
386 | if [ ! -f $DCONF_DEST_USER_DIR/user ]; then
387 | if [ -f $REALHOME/.config/dconf/user ]; then
388 | ensure_dir_exists $DCONF_DEST_USER_DIR
389 | ln -s $REALHOME/.config/dconf/user $DCONF_DEST_USER_DIR
390 | fi
391 | fi
392 | # symlink the runtime dconf file as well
393 | if [ -r $XDG_RUNTIME_DIR/../dconf/user ]; then
394 | ensure_dir_exists $XDG_RUNTIME_DIR/dconf
395 | ln -sf ../../dconf/user $XDG_RUNTIME_DIR/dconf/user
396 | fi
397 |
398 | # Testability support
399 | append_dir LD_LIBRARY_PATH $SNAP/testability
400 | append_dir LD_LIBRARY_PATH $SNAP/testability/$ARCH
401 | append_dir LD_LIBRARY_PATH $SNAP/testability/$ARCH/mesa
402 |
403 | # Gdk-pixbuf loaders
404 | export GDK_PIXBUF_MODULE_FILE=$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache
405 | export GDK_PIXBUF_MODULEDIR=$RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders
406 | if [ $needs_update = true ] || [ ! -f $GDK_PIXBUF_MODULE_FILE ]; then
407 | rm -f $GDK_PIXBUF_MODULE_FILE
408 | if [ -f $RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders ]; then
409 | async_exec $RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders > $GDK_PIXBUF_MODULE_FILE
410 | fi
411 | fi
412 |
413 | # Icon themes cache
414 | if [ $needs_update = true ]; then
415 | rm -rf $XDG_DATA_HOME/icons
416 | ensure_dir_exists $XDG_DATA_HOME/icons
417 | for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do
418 | # The runtime and theme content snaps should already contain icon caches
419 | # so we skip them to optimise app start time.
420 | if [[ "${data_dirs_array[$i]}" == "$SNAP/data-dir" || "${data_dirs_array[$i]}" == "$RUNTIME/"* ]]; then
421 | continue
422 | fi
423 | for theme in "${data_dirs_array[$i]}/icons/"*; do
424 | if [ -f "$theme/index.theme" -a ! -f "$theme/icon-theme.cache" ]; then
425 | theme_dir=$XDG_DATA_HOME/icons/$(basename "$theme")
426 | if [ ! -d "$theme_dir" ]; then
427 | ensure_dir_exists "$theme_dir"
428 | ln -s $theme/* "$theme_dir"
429 | if [ -f $RUNTIME/usr/sbin/update-icon-caches ]; then
430 | async_exec $RUNTIME/usr/sbin/update-icon-caches "$theme_dir"
431 | elif [ -f $RUNTIME/usr/sbin/update-icon-cache.gtk2 ]; then
432 | async_exec $RUNTIME/usr/sbin/update-icon-cache.gtk2 "$theme_dir"
433 | fi
434 | fi
435 | fi
436 | done
437 | done
438 | fi
439 |
440 | # GTK theme and behavior modifier
441 | # Those can impact the theme engine used by Qt as well
442 | gtk_configs=(gtk-3.0/settings.ini gtk-3.0/bookmarks gtk-2.0/gtkfilechooser.ini)
443 | for f in ${gtk_configs[@]}; do
444 | dest="$XDG_CONFIG_HOME/$f"
445 | if [ ! -L "$dest" ]; then
446 | ensure_dir_exists `dirname $dest`
447 | ln -s $REALHOME/.config/$f $dest
448 | fi
449 | done
450 |
451 | # create symbolic link to ibus socket path for ibus to look up its socket files
452 | # (see comments #3 and #6 on https://launchpad.net/bugs/1580463)
453 | IBUS_CONFIG_PATH=$XDG_CONFIG_HOME/ibus
454 | ensure_dir_exists $IBUS_CONFIG_PATH
455 | [ -d $IBUS_CONFIG_PATH/bus ] && rm -rf $IBUS_CONFIG_PATH/bus
456 | ln -sfn $REALHOME/.config/ibus/bus $IBUS_CONFIG_PATH
457 |
--------------------------------------------------------------------------------