Skip to content

Draft: Introducing new android backend

Florian "sp1rit" requested to merge sp1rit/gtk:android into main

I'm working on an Android backend implementation for GDK/GTK, with the goal of eventually merging it upstream. The aim of this PR is to establish a functional initial implementation that is sufficiently stable to be merged.

Goals and Future Plans

The goal of this PR is to have a working initial implementation that works well enough to be merged. After that my plan is to initially write a "bundler" application that can be pointed to a codebase and configuration to generate the android application directory structure and files and using that then builds a apk. Future efforts after that should then go into implementing still missing features such as OpenGL/Vulkan rendering or integration with GStreamer for the media backend.

Current Status

The implementation currently works on Android 14 (SDK 34) but is missing crucial features and contains several bugs. The plan is to target Android 13 (SDK 33) in the future.

For demonstration purposes, I've attached a copy of both of a simple debug application I've used to test various things with and a somewhat working "port" of my Fidei app.

GTKDemo.apk Fidei.apk
(Note: Both are signed with debug keys, so you'll need to adb install them.)

Issues

As the entire GDK backend is hardly documented, and I'm still trying to understand several aspects. If someone could point me to somewhere or explain how

  • Gdk.FrameClock (IdleFrameClock)
  • Surface/Toplevel/Popup Measuring, Layout, Presentation, and Mapping
  • Gdk.Keymap

is supposed to work, the list of current issues should shrink significantly:

Current Issues

Input

  • missing keyboard input support (Needs GdkKeymap implementation)
  • mouse input is quite busted, often keeping a button "sticked down", even tho the pointer is somewhere else and released
  • Selecting text using the touchscreen uses the android cursor handles for some magical reason but they then can't be moved once text was selected.
    Edit: So as it turns out there is nothing magical about it. Its just that libadwaita (1.2) has its text handles styled exactly like how the text handles from Android look 🙃.
  • Basic IME support needed (just letting GTK have control of open/hide OSK)

Window Management

  • Toplevels with the modal property cause all inputs to stop working once closed
  • Initial opening of a GtkPopoverMenu triggers 15+ re-layouts, wasting redraws
  • Clicking "select" in the Gtk.FontPicker doesn't close the dialog
  • Sometimes windows don't appear, or the GlueActivity doesn't trigger Application.activate as needed to spawn a new window

Other

  • a bunch of memory leaks probably
  • maybe some Java object local ref leaks too
  • basically no exception handling. It typically just crashes in the next jni call.

Out of Scope for This PR

As already mentioned, some more advanced things will be added later

  • OpenGL rendering (should be fairly straightforward given Android uses EGL)
  • Vulkan rendering
  • Full IME support (I have no idea how I could ever combine both InputConnection and GtkIMContext)

Required Changes in Other Projects

Cairo

- I've needed to add CAIRO_FORMAT_ABGR32 as a format, as that happened to be the format that the ANativeSurface uses (theoretically CAIRO_FORMAT_RGBA32 is also needed for big endian devices, but no such device running android exists)

  • clang (at least the one shipped with the NDK) has the weird property of setting __GNUC__, even when --std is not set to a gnu variant. This resulted in some macro expecting the compiler to support some GNU intrinsic that is only available under --std=gnu*. For now I've just changed the std to gnu, but instead the macro should probably be updated instead to block out clang (see cairo!580)

GLib

  • No mechanism to prevent the initial g_application_activate call from g_application_run using GtkApplicationImpls. I've just temporarily commented that out.
  • g_set_user_dirs needs to be an exported symbol, as I have not yet added any special android handling to glib, instead the glue code just calls g_set_user_dirs.

GdkPixbuf

  • Not technically necessary, but I've wanted SVG support and as pixbuf loaders are currently not working I've just hacked together the librsvg pixbuf loader with GdkPixbuf as a builtin loader using an ancient version of librsvg.

Other

  • libffi suffers from the same __GNUC__ issue as cairo, currently same solution (see libffi#851)
Edited by Florian "sp1rit"

Merge request reports