Skip to content

Instantly share code, notes, and snippets.

@lupyuen
Last active July 9, 2020 11:37
Show Gist options
  • Save lupyuen/6a2d0b2f4a5680cd65b0a34460886ed6 to your computer and use it in GitHub Desktop.
Save lupyuen/6a2d0b2f4a5680cd65b0a34460886ed6 to your computer and use it in GitHub Desktop.
Simple Wayland App for PinePhone on Ubuntu Touch
/* Connect to Wayland display and create shell surface
(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 Wayland app:
gcc \
-o wayland \
wayland.c \
-lwayland-client \
-lwayland-server \
-Wl,-Map=wayland.map
(3) Overwrite the camera app with the Wayland app:
sudo mount -o remount,rw /
sudo cp wayland /usr/share/click/preinstalled/.click/users/@all/com.ubuntu.camera/camera-app
(4) Run the camera app
(5) Check Logviewer for the output under camera app:
Tip: To copy files to PinePhone via SSH:
scp -i ~/.ssh/id_rsa wayland.* phablet@192.168.1.139:
Based on https://jan.newmarch.name/Wayland/ProgrammingClient/
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-client-protocol.h>
#include <wayland-egl.h>
extern char **environ;
struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct wl_surface *surface;
struct wl_shell *shell;
struct wl_shell_surface *shell_surface;
static void
global_registry_handler(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)
{
if (strcmp(interface, "wl_compositor") == 0) {
// Get Wayland compositor
compositor = wl_registry_bind(registry,
id,
&wl_compositor_interface,
1);
} else if (strcmp(interface, "wl_shell") == 0) {
// Get Wayland shell
shell = wl_registry_bind(registry, id,
&wl_shell_interface, 1);
}
}
static void
global_registry_remover(void *data, struct wl_registry *registry, uint32_t id)
{
printf("Got a registry losing event for %d\n", id);
}
static const struct wl_registry_listener registry_listener = {
global_registry_handler,
global_registry_remover
};
int main(int argc, char **argv) {
// 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]);
}
// Connect to Wayland display
display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "Can't connect to Wayland display\n");
exit(1);
}
printf("Connected to Wayland display\n");
struct wl_registry *registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, NULL);
// Get Wayland compositor
wl_display_dispatch(display);
wl_display_roundtrip(display);
if (compositor == NULL) {
fprintf(stderr, "Can't find Wayland compositor\n");
exit(1);
} else {
fprintf(stderr, "Found Wayland compositor\n");
}
// Create Wayland surface
surface = wl_compositor_create_surface(compositor);
if (surface == NULL) {
fprintf(stderr, "Can't create Wayland surface\n");
exit(1);
} else {
fprintf(stderr, "Created Wayland surface\n");
}
// Create Wayland shell surface
shell_surface = wl_shell_get_shell_surface(shell, surface);
if (shell_surface == NULL) {
fprintf(stderr, "Can't create Wayland shell surface\n");
exit(1);
} else {
fprintf(stderr, "Created Wayland shell surface\n");
}
wl_shell_surface_set_toplevel(shell_surface);
// Disconnect Wayland display
wl_display_disconnect(display);
printf("Disconnected from Wayland display\n");
exit(0);
}
/* Output:
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=2897
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-8dpMG7QgBW
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-UlQNU2x8r6Fj/agent.2842
SHELL=/bin/bash
GDMSESSION=ubuntu-touch
NATIVE_ORIENTATION=Portrait
UPSTART_SESSION=unix:abstract=/com/ubuntu/upstart-session/32011/2842
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
PULSE_PROP=media.role=multimedia
GNOME_KEYRING_CONTROL=
PULSE_PLAYBACK_CORK_STALLED=1
GNOME_KEYRING_PID=
UBUNTU_APP_LAUNCH_XMIR_PATH=/usr/bin/libertine-xmir
LIMA_DEBUG=notiling
MIR_SOCKET=/run/user/32011/mir_socket
QML_NO_TOUCH_COMPRESSION=1
QT_ENABLE_GLYPH_CACHE_WORKAROUND=1
UBUNTU_PLATFORM_API_BACKEND=desktop_mirclient
MIR_SERVER_PROMPT_FILE=1
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=19286
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
Connected to Wayland display
Found Wayland compositor
Created Wayland surface
Created Wayland shell surface
Disconnected from Wayland display
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