Last active
July 10, 2020 11:56
-
-
Save lupyuen/4e878b2540cfb891ef1aadb201f79a87 to your computer and use it in GitHub Desktop.
Simple GTK3 App for Ubuntu Touch on PinePhone
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Simple GTK3 App for Ubuntu Touch on PinePhone | |
(1) Make a copy of the camera app: | |
cp /usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/camera-app $HOME | |
(2) Build the GTK app: | |
gcc \ | |
-g \ | |
-o gtk \ | |
gtk.c \ | |
`pkg-config --cflags --libs gtk+-wayland-3.0` \ | |
-Wl,-Map=gtk.map | |
(3) Overwrite the camera app with the GTK app: | |
sudo mount -o remount,rw / | |
sudo cp gtk /usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/camera-app | |
TODO: | |
rm -rf /run/user/32011/dconf/ | |
(4) Run the camera app | |
Tap the Camera icon in the menu | |
Check for errors in /var/log/syslog, /home/phablet/.cache/upstart/application-click-com.ubuntu.camera_camera_3.1.3.log | |
Also check in Logviewer under "v3.1.3 camera", "dbus" and "unity8" | |
Logviewer hangs if the log file is too huge. If it happens, delete the log: /home/phablet/.cache/upstart/application-click-com.ubuntu.camera_camera_3.1.3.log | |
If gtk_application_new() name is NULL: | |
See complete log at https://gist.github.com/lupyuen/2380a6a6f121d16ce7588f77497c7e1d | |
(camera-app:10232): dconf-WARNING **: unable to open named profile (/tmp/camera-dconf): using the null configuration. | |
** (camera-app:10232): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files | |
(camera-app:10232): Gtk-WARNING **: Failed to parse /etc/gtk-3.0/settings.ini: Permission denied | |
Error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name com.canonical.PropertyService was not provided by any .service files | |
Jul 10 15:41:34 ubuntu-phablet kernel: [ 3442.203468] audit: type=1400 audit(1594366894.725:196): | |
apparmor="DENIED" operation="open" profile="com.ubuntu.camera_camera_3.1.3" name="/etc/gtk-3.0/settings.ini" pid=10232 comm="camera-app" requested_mask="r" denied_mask="r" fsuid=32011 ouid=0 | |
If gtk_application_new() name is "com.ubuntu.camera": | |
Failed to register: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied: | |
Connection ":1.101" is not allowed to own the service "com.ubuntu.camera" | |
due to AppArmor policy | |
Error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name | |
com.canonical.PropertyService was not provided by any .service files | |
dbus[2936]: apparmor="DENIED" operation="dbus_bind" bus="session" | |
name="com.ubuntu.camera" mask="bind" pid=8310 label="com.ubuntu.camera_camera_3.1.3" | |
If gtk_application_new() name is "com.ubuntu.camera_camera_3.1.3": | |
(process:13280): Gtk-CRITICAL **: gtk_application_new: assertion | |
'application_id == NULL || g_application_id_is_valid (application_id)' failed | |
(process:13280): GLib-GObject-WARNING **: invalid (NULL) pointer instance | |
(process:13280): GLib-GObject-CRITICAL **: g_signal_connect_data: | |
assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed | |
(process:13280): GLib-GIO-CRITICAL **: g_application_run: assertion | |
'G_IS_APPLICATION (application)' failed | |
Error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: | |
The name com.canonical.PropertyService was not provided by any .service files | |
Tip: To copy files to PinePhone via SSH: | |
scp -i ~/.ssh/id_rsa gtk.* phablet@192.168.1.160: | |
View AppArmor Profiles: | |
sudo apt install apparmor-utils | |
sudo aa-confined | |
cat /etc/apparmor.d/usr.bin.messaging-app | |
Based on the C sample from https://www.gtk.org | |
*/ | |
#include <gtk/gtk.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
extern char **environ; | |
/// Handle activation of our app by rendering the UI controls | |
static void on_activate (GtkApplication *app) { | |
puts("App activated"); | |
// Create a new window | |
puts("Create window..."); | |
GtkWidget *window = gtk_application_window_new (app); | |
// Create a new button | |
// puts("Create button..."); | |
// GtkWidget *button = gtk_button_new_with_label ("Hello, World!"); | |
// When the button is clicked, destroy the window passed as an argument | |
// puts("Connect button..."); | |
// g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window); | |
// Add the button to the window | |
// puts("Add button..."); | |
// gtk_container_add (GTK_CONTAINER (window), button); | |
// Show the window | |
puts("Show window..."); | |
gtk_widget_show_all (window); | |
} | |
int main (int argc, char *argv[]) { | |
// Set DCONF profile, because the default profile folder is blocked by AppArmor: run/user/32011/dconf/ | |
setenv("DCONF_PROFILE", "/tmp/camera-dconf", 1); | |
// Set GTK backend to Wayland | |
// setenv("GDK_BACKEND", "wayland", 1); | |
// Set GTK backend to Mir | |
// setenv("GDK_BACKEND", "mir", 1); | |
// Show GTK debugging messages | |
setenv("GTK_DEBUG", "actions,builder,geometry,icontheme,keybindings,misc,modules,plugsocket,pixel-cache,printing,size-request,text,tree", 1); | |
// Show command-line parameters | |
for (int i = 0; i < argc; i++) { | |
printf("argv[%d]=%s\n", i, argv[i]); | |
} | |
// Show environment | |
for (int i = 0; environ[i] != NULL; i++) { | |
puts(environ[i]); | |
} | |
// Create a new application | |
// Note: Name must be NULL or the app will be blocked by AppArmor | |
puts("Create app..."); | |
GtkApplication *app = gtk_application_new ( | |
NULL, // Name must be NULL to prevent AppArmor dbus_bind error | |
G_APPLICATION_NON_UNIQUE // Don't check for other instances of this app. Previously G_APPLICATION_FLAGS_NONE | |
); | |
// Set the app activation callback | |
puts("Connect app..."); | |
g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL); | |
// Run the app. Will block until the app terminates. | |
puts("Run app..."); | |
int status = g_application_run (G_APPLICATION (app), argc, argv); | |
printf("Exit status %d\n", status); | |
} | |
/* Output: | |
+++ pkg-config --cflags --libs gtk+-wayland-3.0 | |
++ gcc -g -o gtk gtk.c -pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/aarch64-linux-gnu/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/mirclient -I/usr/include/mircore -I/usr/include/mircookie -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng12 -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -Wl,-Map=gtk.map | |
++ sudo mount -o remount,rw / | |
++ sudo cp gtk /usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/camera-app | |
++ ls -l /usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/camera-app | |
-rwxr-xr-x 1 clickpkg clickpkg 17656 Jul 10 19:54 /usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/camera-app | |
++ echo | |
++ tail -f /home/phablet/.cache/upstart/application-click-com.ubuntu.camera_camera_3.1.3.log | |
argv[0]=./camera-app | |
PATH=/usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/lib/aarch64-linux-gnu/bin:/usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera:/home/phablet/go-1.14.4/bin:/home/phablet/go-1.13.6/bin:/usr/lib/go-1.13.6/bin:/home/phablet/bin:/home/phablet/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin | |
TERM=linux | |
GRID_UNIT_PX=14 | |
LANGUAGE=en_US:en | |
USER=phablet | |
XDG_SEAT=seat0 | |
EXTERNAL_STORAGE=/mnt/sdcard | |
HOSTNAME=android | |
XDG_SESSION_TYPE=mir | |
LOOP_MOUNTPOINT=/mnt/obb | |
SSH_AGENT_PID=2892 | |
SHLVL=1 | |
HOME=/home/phablet | |
DESKTOP_SESSION=ubuntu-touch | |
XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 | |
ANDROID_ASSETS=/system/app | |
GOROOT= | |
QML2_IMPORT_PATH=/usr/lib/aarch64-linux-gnu/qt5/imports:/usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/lib/aarch64-linux-gnu | |
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-MFuzagleui | |
QT_EXCLUDE_GENERIC_BEARER=1 | |
QT_WAYLAND_DISABLE_WINDOWDECORATION=1 | |
QT_QPA_PLATFORMTHEME=ubuntuappmenu | |
GTK_IM_MODULE=Maliit | |
LOGNAME=phablet | |
QT_SELECT=qt5 | |
QT_WAYLAND_FORCE_DPI=96 | |
QTWEBKIT_DPR=1 | |
FLASH_KERNEL_SKIP=true | |
XDG_SESSION_ID=c1 | |
QT_FILE_SELECTORS=ubuntu-touch | |
MKSH=/system/bin/sh | |
ANDROID_DATA=/data | |
GDM_LANG=en_US | |
XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0 | |
ANDROID_ROOT=/system | |
XDG_RUNTIME_DIR=/run/user/32011 | |
LANG=en_US.UTF-8 | |
XDG_CURRENT_DESKTOP=Unity | |
MIR_SERVER_WAYLAND_HOST=/tmp/wayland-root | |
XDG_SESSION_DESKTOP=ubuntu-touch | |
QV4_ENABLE_JIT_CACHE=1 | |
XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/phablet | |
SSH_AUTH_SOCK=/tmp/ssh-c6x2sUdjapqR/agent.2851 | |
SHELL=/bin/bash | |
GDMSESSION=ubuntu-touch | |
NATIVE_ORIENTATION=Portrait | |
UPSTART_SESSION=unix:abstract=/com/ubuntu/upstart-session/32011/2851 | |
ASEC_MOUNTPOINT=/mnt/asec | |
QT_IM_MODULE=maliitphablet | |
XDG_VTNR=1 | |
PWD=/home/phablet | |
QT_QPA_PLATFORM=wayland | |
ANDROID_PROPERTY_WORKSPACE=8,49152 | |
XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu-touch:/etc/xdg/xdg-ubuntu-touch:/etc/xdg | |
XDG_DATA_DIRS=/usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera:/usr/share/ubuntu-touch:/usr/share/ubuntu-touch:/usr/local/share/:/usr/share/:/custom/usr/share/ | |
MIR_SERVER_NAME=session-0 | |
ANDROID_BOOTLOGO=1 | |
ANDROID_CACHE=/cache | |
PULSE_SCRIPT=/etc/pulse/touch.pa | |
PULSE_CLIENTCONFIG=/etc/pulse/touch-client.conf | |
GNOME_KEYRING_CONTROL= | |
PULSE_PROP=media.role=multimedia | |
GNOME_KEYRING_PID= | |
PULSE_PLAYBACK_CORK_STALLED=1 | |
UBUNTU_APP_LAUNCH_XMIR_PATH=/usr/bin/libertine-xmir | |
LIMA_DEBUG=notiling | |
MIR_SOCKET=/run/user/32011/mir_socket | |
MIR_SERVER_PROMPT_FILE=1 | |
QML_NO_TOUCH_COMPRESSION=1 | |
QT_ENABLE_GLYPH_CACHE_WORKAROUND=1 | |
UBUNTU_PLATFORM_API_BACKEND=desktop_mirclient | |
UBUNTU_APP_LAUNCH_ARCH=aarch64-linux-gnu | |
UBUNTU_APPLICATION_ISOLATION=1 | |
XDG_CACHE_HOME=/home/phablet/.cache | |
XDG_CONFIG_HOME=/home/phablet/.config | |
XDG_DATA_HOME=/home/phablet/.local/share | |
TMPDIR=/run/user/32011/confined/com.ubuntu.camera | |
__GL_SHADER_DISK_CACHE_PATH=/home/phablet/.cache/com.ubuntu.camera | |
APP_DIR=/usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera | |
APP_DESKTOP_FILE_PATH=/usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/camera-app.desktop | |
APP_XMIR_ENABLE=0 | |
APP_EXEC=./camera-app %u | |
APP_ID=com.ubuntu.camera_camera_3.1.3 | |
APP_LAUNCHER_PID=3355 | |
UPSTART_JOB=application-click | |
UPSTART_INSTANCE=com.ubuntu.camera_camera_3.1.3 | |
LD_LIBRARY_PATH=/usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/lib/aarch64-linux-gnu:/usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/lib | |
DCONF_PROFILE=/tmp/camera-dconf | |
GTK_DEBUG=actions,builder,geometry,icontheme,keybindings,misc,modules,plugsocket,pixel-cache,printing,size-request,text,tree | |
Create app... | |
Connect app... | |
Run app... | |
(camera-app:11330): dconf-WARNING **: unable to open named profile (/tmp/camera-dconf): using the null configuration. | |
** (camera-app:11330): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files | |
App activated | |
Create window... | |
(camera-app:11330): Gtk-WARNING **: Failed to parse /etc/gtk-3.0/settings.ini: Permission denied | |
gtk-modules setting changed to: (null) | |
Show window... | |
[0xb9c62a0] GtkApplicationWindow height for width: -1 is minimum 52 and natural: 252 (hit cache: no) | |
[0xb9c62a0] GtkApplicationWindow width for height: -1 is minimum 52 and natural: 200 (hit cache: no) | |
[0xb9c62a0] GtkApplicationWindow width for height: -1 is minimum 52 and natural: 200 (hit cache: yes) | |
[0xb9c62a0] GtkApplicationWindow height for width: -1 is minimum 52 and natural: 252 (hit cache: yes) | |
gtk_widget_size_allocate: GtkApplicationWindow 0 0 200 252 | |
[0xb9c62a0] GtkApplicationWindow height for width: -1 is minimum 52 and natural: 252 (hit cache: yes) | |
[0xb9c62a0] GtkApplicationWindow width for height: -1 is minimum 52 and natural: 200 (hit cache: yes) | |
[0xba52170] GtkLabel height for width: -1 is minimum 18 and natural: 18 (hit cache: no) | |
[0xba291c0] GtkBox height for width: -1 is minimum 18 and natural: 18 (hit cache: no) | |
[0xba0b190] GtkHeaderBar height for width: -1 is minimum 18 and natural: 18 (hit cache: no) | |
[0xb9c62a0] GtkApplicationWindow height for width: -1 is minimum 70 and natural: 270 (hit cache: no) | |
[0xba52170] GtkLabel width for height: -1 is minimum 50 and natural: 50 (hit cache: no) | |
[0xba291c0] GtkBox width for height: -1 is minimum 50 and natural: 50 (hit cache: no) | |
[0xba0b190] GtkHeaderBar width for height: -1 is minimum 64 and natural: 64 (hit cache: no) | |
[0xb9c62a0] GtkApplicationWindow width for height: -1 is minimum 116 and natural: 200 (hit cache: no) | |
[0xb9c62a0] GtkApplicationWindow width for height: -1 is minimum 116 and natural: 200 (hit cache: yes) | |
[0xb9c62a0] GtkApplicationWindow height for width: -1 is minimum 70 and natural: 270 (hit cache: yes) | |
gtk_widget_size_allocate: GtkApplicationWindow 0 0 252 304 | |
[0xb9c62a0] GtkApplicationWindow height for width: -1 is minimum 70 and natural: 270 (hit cache: yes) | |
[0xb9c62a0] GtkApplicationWindow width for height: -1 is minimum 116 and natural: 200 (hit cache: yes) | |
[0xba0b190] GtkHeaderBar height for width: -1 is minimum 18 and natural: 18 (hit cache: yes) | |
gtk_widget_size_allocate: GtkHeaderBar 26 23 200 18 | |
[0xba0b190] GtkHeaderBar height for width: -1 is minimum 18 and natural: 18 (hit cache: yes) | |
[0xba0b190] GtkHeaderBar width for height: -1 is minimum 64 and natural: 64 (hit cache: yes) | |
[0xba52490] GtkLabel width for height: -1 is minimum 74 and natural: 122 (hit cache: no) | |
[0xba29300] GtkBox width for height: -1 is minimum 74 and natural: 122 (hit cache: no) | |
gtk_widget_size_allocate: GtkBox 65 23 122 18 | |
[0xba52490] GtkLabel height for width: -1 is minimum 18 and natural: 18 (hit cache: no) | |
[0xba29300] GtkBox height for width: -1 is minimum 18 and natural: 18 (hit cache: no) | |
[0xba29300] GtkBox width for height: -1 is minimum 74 and natural: 122 (hit cache: yes) | |
[0xba52490] GtkLabel height for width: -1 is minimum 18 and natural: 18 (hit cache: yes) | |
gtk_widget_size_allocate: GtkLabel 65 23 122 18 | |
[0xba52490] GtkLabel height for width: -1 is minimum 18 and natural: 18 (hit cache: yes) | |
[0xba52490] GtkLabel width for height: -1 is minimum 74 and natural: 122 (hit cache: yes) | |
gtk_widget_set_clip: GtkLabel 65 23 122 18 | |
gtk_widget_set_clip: GtkBox 65 23 122 18 | |
gtk_widget_set_clip: GtkHeaderBar 26 23 200 18 | |
Error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name com.canonical.PropertyService was not provided by any .service files | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment