diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 69b58791..f84b3e25 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -36,7 +36,7 @@ jobs: # unzip linux-x64-embedder # mv libflutter_engine.so ${{github.workspace}}/build run: | - curl -L https://github.com/sony/flutter-embedded-linux/releases/latest/download/elinux-x64-release.zip > elinux-x64-release.zip + curl -L https://github.com/flutter-elinux/flutter-embedded-linux/releases/latest/download/elinux-x64-release.zip > elinux-x64-release.zip unzip elinux-x64-release.zip mv libflutter_engine.so ${{github.workspace}}/build diff --git a/AUTHORS b/AUTHORS index 6a816263..fd5477a2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -18,3 +18,8 @@ Sebastian Urban Athaariq Ardhiansyah Anton Sakhon Bari Rao +Frede Emil Hoey Braendstrup +Dominique Martinet +Wang Bin +Jón Bjarni Bjarnason +Fredrik Magnussen diff --git a/README.md b/README.md index c5c6bd64..7707e0cc 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ # Embedded Linux (eLinux) embedding for Flutter -![image](https://github.com/sony/flutter-elinux/blob/main/doc/images/overview.png) +![image](https://github.com/flutter-elinux/flutter-elinux/blob/main/doc/images/overview.png) -[![build-test](https://github.com/sony/flutter-embedded-linux/actions/workflows/build-test.yml/badge.svg)](https://github.com/sony/flutter-embedded-linux/actions/workflows/build-test.yml) +[![build-test](https://github.com/flutter-elinux/flutter-embedded-linux/actions/workflows/build-test.yml/badge.svg)](https://github.com/flutter-elinux/flutter-embedded-linux/actions/workflows/build-test.yml) This project was created to develop **non-official** embedded Linux embeddings of [Flutter](https://flutter.dev/). This embedder is focusing on embedded Linux (eLinux) system use cases. It is also implemented based on Flutter desktop for Windows and has some unique features to use it in embedded systems. -If you develop flutter apps for eLinux, use [flutter-elinux](https://github.com/sony/flutter-elinux), which is a non-official extension to the [Flutter SDK](https://github.com/flutter/flutter) to build and debug Flutter apps for embedded Linux devices. +If you develop flutter apps for eLinux, use [flutter-elinux](https://github.com/flutter-elinux/flutter-elinux), which is a non-official extension to the [Flutter SDK](https://github.com/flutter/flutter) to build and debug Flutter apps for embedded Linux devices. ### Repositories -- [flutter-elinux](https://github.com/sony/flutter-elinux): Flutter tools for eLinux -- [flutter-elinux-plugins](https://github.com/sony/flutter-elinux-plugins): Flutter plugins for eLinux -- [flutter-embedded-linux](https://github.com/sony/flutter-embedded-linux): eLinux embedding for Flutter -- [meta-flutter](https://github.com/sony/meta-flutter): Yocto recipes of eLinux embedding for Flutter +- [flutter-elinux](https://github.com/flutter-elinux/flutter-elinux): Flutter tools for eLinux +- [flutter-elinux-plugins](https://github.com/flutter-elinux/flutter-elinux-plugins): Flutter plugins for eLinux +- [flutter-embedded-linux](https://github.com/flutter-elinux/flutter-embedded-linux): eLinux embedding for Flutter +- [meta-flutter](https://github.com/flutter-elinux/meta-flutter): Yocto recipes of eLinux embedding for Flutter ## Objective & Goal Our objective is to use Flutter in embedded systems. We're developing this embedder to use Flutter in embedded products. Ultimately we would like to propose and contribute this software to the mainline of [Flutter Engine](https://github.com/flutter/engine), which means we would like to add an embedded systems version into the Flutter repo for all embedded developers. Please note that this is just our ideal, not the official opinion of the Flutter community. @@ -21,7 +21,7 @@ We would be grateful if you could give us feedback on bugs and new feature reque ## Features - Flutter embedder optimized for Embedded Systems - - Lightweight than Flutter desktop for Linux (Not using X11 and GTK) + - Lighter than Flutter desktop for Linux (Not using X11 and GTK) - Minimal dependent libraries - The main target of this embedder is Arm64 devices. We haven't confirmed in Arm 32bit (ARMv7, armhf) devices - Display backend support @@ -34,10 +34,14 @@ We would be grateful if you could give us feedback on bugs and new feature reque - Keyboard, mouse and touch inputs support - Equivalent quality to Flutter desktops - API compatibility with Flutter desktop for Windows and GLFW - - APIs such as MethodChannel and EventChannel are completely the same with them + - APIs such as MethodChannel and EventChannel are completely the same as those in Flutter desktop for Windows and GLFW ## Documentation -Documentation for this software can be found at [Wiki](https://github.com/sony/flutter-embedded-linux/wiki). +Documentation for this software can be found at [Wiki](https://github.com/flutter-elinux/flutter-embedded-linux/wiki). ## Supported platforms -This embedder supports x64 and Arm64 (aarch64, ARMv8) architectures on Linux which supports either Wayland backend or DRM backend. See [Support status](https://github.com/sony/flutter-elinux/wiki/Support-status) for details. +This embedder supports x64 and Arm64 (aarch64, ARMv8) architectures on Linux which supports either Wayland backend or DRM backend. See [Support status](https://github.com/flutter-elinux/flutter-elinux/wiki/Support-status) for details. + +## Thanks + +This repository was previously hosted on [sony/flutter-embedded-linux](https://github.com/sony/flutter-embedded-linux). Thanks to sony for creating this fork and maintaining it for 4 years. diff --git a/examples/README.md b/examples/README.md index ef2e517e..0a626c21 100644 --- a/examples/README.md +++ b/examples/README.md @@ -4,11 +4,11 @@ These are an example of how to use embedded Linux embedding for Flutter. ## Each backend examples -- [flutter-wayland-client](https://github.com/sony/flutter-embedded-linux/tree/master/examples/flutter-wayland-client): Wayland client app -- [flutter-drm-gbm-backend](https://github.com/sony/flutter-embedded-linux/tree/master/examples/flutter-drm-gbm-backend): Fullscreen app on DRM backend with GBM -- [flutter-drm-eglstream-backend](https://github.com/sony/flutter-embedded-linux/tree/master/examples/flutter-drm-eglstream-backend): Fullscreen app on DRM backend with EGLStream -- [flutter-x11-client](https://github.com/sony/flutter-embedded-linux/tree/master/examples/flutter-x11-client): X11 client app +- [flutter-wayland-client](https://github.com/flutter-elinux/flutter-embedded-linux/tree/master/examples/flutter-wayland-client): Wayland client app +- [flutter-drm-gbm-backend](https://github.com/flutter-elinux/flutter-embedded-linux/tree/master/examples/flutter-drm-gbm-backend): Fullscreen app on DRM backend with GBM +- [flutter-drm-eglstream-backend](https://github.com/flutter-elinux/flutter-embedded-linux/tree/master/examples/flutter-drm-eglstream-backend): Fullscreen app on DRM backend with EGLStream +- [flutter-x11-client](https://github.com/flutter-elinux/flutter-embedded-linux/tree/master/examples/flutter-x11-client): X11 client app ## Examples using Flutter Plugins -- [flutter-video-player-plugin](https://github.com/sony/flutter-embedded-linux/tree/master/examples/flutter-video-player-plugin): Flutter video player plugin -- [flutter-external-texture-plugin](https://github.com/sony/flutter-embedded-linux/tree/master/examples/flutter-external-texture-plugin): Flutter external texture plugin +- [flutter-video-player-plugin](https://github.com/flutter-elinux/flutter-embedded-linux/tree/master/examples/flutter-video-player-plugin): Flutter video player plugin +- [flutter-external-texture-plugin](https://github.com/flutter-elinux/flutter-embedded-linux/tree/master/examples/flutter-external-texture-plugin): Flutter external texture plugin diff --git a/examples/flutter-drm-eglstream-backend/cmake/user_config.cmake b/examples/flutter-drm-eglstream-backend/cmake/user_config.cmake index 4d2cb636..9e948f5c 100644 --- a/examples/flutter-drm-eglstream-backend/cmake/user_config.cmake +++ b/examples/flutter-drm-eglstream-backend/cmake/user_config.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) # Flutter embedder configurations. -# See: https://github.com/sony/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options +# See: https://github.com/flutter-elinux/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options set(BACKEND_TYPE DRM-EGLSTREAM) set(USE_GLES3 OFF) diff --git a/examples/flutter-drm-gbm-backend/cmake/user_config.cmake b/examples/flutter-drm-gbm-backend/cmake/user_config.cmake index a3a5931e..c5d1935d 100644 --- a/examples/flutter-drm-gbm-backend/cmake/user_config.cmake +++ b/examples/flutter-drm-gbm-backend/cmake/user_config.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) # Flutter embedder configurations. -# See: https://github.com/sony/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options +# See: https://github.com/flutter-elinux/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options set(BACKEND_TYPE DRM-GBM) set(USE_GLES3 OFF) diff --git a/examples/flutter-external-texture-plugin/cmake/user_config.cmake b/examples/flutter-external-texture-plugin/cmake/user_config.cmake index 5f72786b..ade6aa1c 100644 --- a/examples/flutter-external-texture-plugin/cmake/user_config.cmake +++ b/examples/flutter-external-texture-plugin/cmake/user_config.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) # Flutter embedder configurations. -# See: https://github.com/sony/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options +# See: https://github.com/flutter-elinux/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options set(BACKEND_TYPE WAYLAND) set(USE_GLES3 OFF) diff --git a/examples/flutter-video-player-plugin/README.md b/examples/flutter-video-player-plugin/README.md index 4e643a99..21122727 100644 --- a/examples/flutter-video-player-plugin/README.md +++ b/examples/flutter-video-player-plugin/README.md @@ -1,7 +1,7 @@ # Overview Flutter video player example using video player plugin for Embedded Linux. The interface of the plugin is compatible with [the Flutter official video player plugin](https://github.com/flutter/plugins/tree/master/packages/video_player/video_player). -Note that this is just example for eLinux embedder, so please use [sony/flutter-elinux-plugins/packages/video_player](https://github.com/sony/flutter-elinux-plugins/tree/main/packages/video_player) +Note that this is just example for eLinux embedder, so please use [sony/flutter-elinux-plugins/packages/video_player](https://github.com/flutter-elinux/flutter-elinux-plugins/tree/main/packages/video_player) ![image](https://user-images.githubusercontent.com/62131389/124210378-43f06400-db26-11eb-8723-40dad0eb67b0.png) diff --git a/examples/flutter-video-player-plugin/cmake/user_config.cmake b/examples/flutter-video-player-plugin/cmake/user_config.cmake index 5f72786b..ade6aa1c 100644 --- a/examples/flutter-video-player-plugin/cmake/user_config.cmake +++ b/examples/flutter-video-player-plugin/cmake/user_config.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) # Flutter embedder configurations. -# See: https://github.com/sony/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options +# See: https://github.com/flutter-elinux/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options set(BACKEND_TYPE WAYLAND) set(USE_GLES3 OFF) diff --git a/examples/flutter-wayland-client/cmake/user_config.cmake b/examples/flutter-wayland-client/cmake/user_config.cmake index 5f72786b..ade6aa1c 100644 --- a/examples/flutter-wayland-client/cmake/user_config.cmake +++ b/examples/flutter-wayland-client/cmake/user_config.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) # Flutter embedder configurations. -# See: https://github.com/sony/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options +# See: https://github.com/flutter-elinux/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options set(BACKEND_TYPE WAYLAND) set(USE_GLES3 OFF) diff --git a/examples/flutter-x11-client/cmake/user_config.cmake b/examples/flutter-x11-client/cmake/user_config.cmake index aa0196fc..7a60b713 100644 --- a/examples/flutter-x11-client/cmake/user_config.cmake +++ b/examples/flutter-x11-client/cmake/user_config.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) # Flutter embedder configurations. -# See: https://github.com/sony/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options +# See: https://github.com/flutter-elinux/flutter-embedded-linux/wiki/Building-Embedded-Linux-embedding-for-Flutter#user-configuration-parameters-cmake-options set(BACKEND_TYPE X11) set(USE_GLES3 OFF) diff --git a/release/.gitignore b/release/.gitignore new file mode 100644 index 00000000..0743ec92 --- /dev/null +++ b/release/.gitignore @@ -0,0 +1,5 @@ +/home +/build-embedder +/depot_tools +/output* +/work-* diff --git a/release/Dockerfile b/release/Dockerfile new file mode 100644 index 00000000..e80a3fda --- /dev/null +++ b/release/Dockerfile @@ -0,0 +1,55 @@ +# Build releases with the oldest possible supported target +# The built binaries will depend on symbols from the libc used here, +# so this should work on newer OS but might not work on older OS + +# Recommended version should be kept in sync with the wiki: +# https://github.com/flutter-elinux/flutter-elinux/wiki/flutter-elinux-install +FROM debian:bullseye-slim + +ENV DEBIAN_FRONTEND noninteractive + +RUN </dev/null || true + +echo "" +echo "Engine version: ${ENGINE_VERSION}" +echo "Channel: ${CHANNEL}" +echo "" +echo "Output packages:" +echo " - elinux-common.zip" +echo " - elinux-x64-debug.zip" +echo " - elinux-x64-profile.zip" +echo " - elinux-x64-release.zip" +echo " - elinux-arm64-debug.zip" +echo " - elinux-arm64-profile.zip" +echo " - elinux-arm64-release.zip" +echo "" +echo "All artifacts are ready for release!" +echo "==========================================" + +# Cleanup option (uncomment if you want to clean up work directories) +# echo "" +# echo "Cleaning up work directories..." +# rm -rf ${WORK_DIR_X64} ${WORK_DIR_ARM64} +# echo "Cleanup completed." diff --git a/release/build-flutter-embedder.sh b/release/build-flutter-embedder.sh new file mode 100755 index 00000000..b675c4e8 --- /dev/null +++ b/release/build-flutter-embedder.sh @@ -0,0 +1,193 @@ +#!/usr/bin/env bash + +set -ex + +# Example) +# +# ./build-flutter-embedder.sh --arch=arm64 --output-dir=artifacts --engine-dir=../build-embedder/flutter/engine +# + +TARGET_ARCH=${TARGET_ARCH:-"x64"} +OUTPUT_DIR=${OUTPUT_DIR:-"artifacts"} +EMBEDDER_REPO=${EMBEDDER_REPO:-"https://github.com/flutter-elinux/flutter-embedded-linux.git"} +ENGINE_DIR=${ENGINE_DIR:-""} +RUNTIME_MODE=${RUNTIME_MODE:-"release"} +INSTALL_DIR=${INSTALL_DIR:-"/usr/lib"} + +export CMAKE_BUILD_PARALLEL_LEVEL=24 + +for i; do + case $i in + --arch=*) + TARGET_ARCH="${i#*=}" + ;; + --output-dir=*) + OUTPUT_DIR="${i#*=}" + ;; + --embedder-repo=*) + EMBEDDER_REPO="${i#*=}" + ;; + --engine-dir=*) + ENGINE_DIR="${i#*=}" + ;; + --runtime-mode=*) + RUNTIME_MODE="${i#*=}" + ;; + --install-dir=*) + INSTALL_DIR="${i#*=}" + esac +done + +# Validate ENGINE_DIR +if [ -z "${ENGINE_DIR}" ]; then + echo "Error: ENGINE_DIR is not set. Please specify --engine-dir=" + echo "Example: --engine-dir=../build-embedder/flutter/engine" + exit 1 +fi + +if [ ! -d "${ENGINE_DIR}" ]; then + echo "Error: ENGINE_DIR does not exist: ${ENGINE_DIR}" + exit 1 +fi + +ABS_INSTALL_DIR=$(realpath ${INSTALL_DIR}) + +echo "Engine directory: ${ENGINE_DIR}" +echo "Target architecture: ${TARGET_ARCH}" +echo "Runtime mode: ${RUNTIME_MODE}" + +# Determine output directories based on architecture +if [ ${TARGET_ARCH} = "arm64" ]; then + ARCH_ARGS="-DCMAKE_TOOLCHAIN_FILE=$PWD/cross-toolchain-aarch64.cmake" + DEBUG_OUTDIR="linux_debug_unopt_arm64" + PROFILE_OUTDIR="linux_profile_arm64" + RELEASE_OUTDIR="linux_release_arm64" +else + DEBUG_OUTDIR="host_debug_unopt" + PROFILE_OUTDIR="host_profile" + RELEASE_OUTDIR="host_release" +fi + +# Install libflutter_engine.so from built engine +install_flutter_engine() { + + echo "Installing Flutter Engine to ${ABS_INSTALL_DIR}" + mkdir -p ${ABS_INSTALL_DIR} + + # Copy libflutter_engine.so files + cp ${ENGINE_DIR}/src/out/${DEBUG_OUTDIR}/libflutter_engine.so ${ABS_INSTALL_DIR}/libflutter_engine-debug.so + cp ${ENGINE_DIR}/src/out/${PROFILE_OUTDIR}/libflutter_engine.so ${ABS_INSTALL_DIR}/libflutter_engine-profile.so + cp ${ENGINE_DIR}/src/out/${RELEASE_OUTDIR}/libflutter_engine.so ${ABS_INSTALL_DIR}/libflutter_engine-release.so + + # Create symlink based on runtime mode + ln -sf ./libflutter_engine-${RUNTIME_MODE}.so ${ABS_INSTALL_DIR}/libflutter_engine.so + + echo "Flutter Engine installed successfully." +} + +# Install build dependencies (uncomment if needed) +# install_dependencies() { +# apt install -y zip equivs clang libgles2-mesa-dev wayland-protocols libegl1-mesa-dev +# apt install -y libdrm-dev libgbm-dev libinput-dev libudev-dev libsystemd-dev +# apt install -y libxkbcommon-dev libwayland-dev +# } + +# Creates artifacts directory +mkdir -p ${OUTPUT_DIR}/${TARGET_ARCH}/debug +mkdir -p ${OUTPUT_DIR}/${TARGET_ARCH}/release +mkdir -p ${OUTPUT_DIR}/common + +# Install libflutter_engine.so from the built engine +install_flutter_engine + +# Get source files +if ! [ -d flutter-embedded-linux ]; then + git clone --filter blob:none ${EMBEDDER_REPO} +else + git -C flutter-embedded-linux fetch + git -C flutter-embedded-linux reset --hard origin/master +fi +cd flutter-embedded-linux +git rev-parse --short HEAD > ../${OUTPUT_DIR}/embedder.version +cat ../${OUTPUT_DIR}/embedder.version +mkdir -p build +cd build + +# Build wayland (for debug mode) +cp ${ABS_INSTALL_DIR}/libflutter_engine.so . +cmake $ARCH_ARGS -DBUILD_ELINUX_SO=ON -DBACKEND_TYPE=WAYLAND -DCMAKE_BUILD_TYPE=Release -DENABLE_ELINUX_EMBEDDER_LOG=ON -DFLUTTER_RELEASE=OFF .. +cmake --build . +cp libflutter_elinux_wayland.so ../../${OUTPUT_DIR}/${TARGET_ARCH}/debug +rm -rf * + +# Build wayland (for release mode) +cp ${ABS_INSTALL_DIR}/libflutter_engine.so . +cmake $ARCH_ARGS -DBUILD_ELINUX_SO=ON -DBACKEND_TYPE=WAYLAND -DCMAKE_BUILD_TYPE=Release -DENABLE_ELINUX_EMBEDDER_LOG=OFF -DFLUTTER_RELEASE=ON .. +cmake --build . +cp libflutter_elinux_wayland.so ../../${OUTPUT_DIR}/${TARGET_ARCH}/release +rm -rf * + +# Build x11 (for debug mode) +cp ${ABS_INSTALL_DIR}/libflutter_engine.so . +cmake $ARCH_ARGS -DBUILD_ELINUX_SO=ON -DBACKEND_TYPE=X11 -DCMAKE_BUILD_TYPE=Release -DENABLE_ELINUX_EMBEDDER_LOG=ON -DFLUTTER_RELEASE=OFF .. +cmake --build . +cp libflutter_elinux_x11.so ../../${OUTPUT_DIR}/${TARGET_ARCH}/debug +rm -rf * + +# Build x11 (for release mode) +cp ${ABS_INSTALL_DIR}/libflutter_engine.so . +cmake $ARCH_ARGS -DBUILD_ELINUX_SO=ON -DBACKEND_TYPE=X11 -DCMAKE_BUILD_TYPE=Release -DENABLE_ELINUX_EMBEDDER_LOG=OFF -DFLUTTER_RELEASE=ON .. +cmake --build . +cp libflutter_elinux_x11.so ../../${OUTPUT_DIR}/${TARGET_ARCH}/release +rm -rf * + +# Build gbm (for debug mode) +cp ${ABS_INSTALL_DIR}/libflutter_engine.so . +cmake $ARCH_ARGS -DBUILD_ELINUX_SO=ON -DBACKEND_TYPE=DRM-GBM -DCMAKE_BUILD_TYPE=Release -DENABLE_ELINUX_EMBEDDER_LOG=ON -DFLUTTER_RELEASE=OFF .. +cmake --build . +cp libflutter_elinux_gbm.so ../../${OUTPUT_DIR}/${TARGET_ARCH}/debug +rm -rf * + +# Build gbm (for release mode) +cp ${ABS_INSTALL_DIR}/libflutter_engine.so . +cmake $ARCH_ARGS -DBUILD_ELINUX_SO=ON -DBACKEND_TYPE=DRM-GBM -DCMAKE_BUILD_TYPE=Release -DENABLE_ELINUX_EMBEDDER_LOG=OFF -DFLUTTER_RELEASE=ON .. +cmake --build . +cp libflutter_elinux_gbm.so ../../${OUTPUT_DIR}/${TARGET_ARCH}/release +rm -rf * + +# Build eglstream (for debug mode) +cp ${ABS_INSTALL_DIR}/libflutter_engine.so . +cmake $ARCH_ARGS -DBUILD_ELINUX_SO=ON -DBACKEND_TYPE=DRM-EGLSTREAM -DCMAKE_BUILD_TYPE=Release -DENABLE_ELINUX_EMBEDDER_LOG=ON -DFLUTTER_RELEASE=OFF .. +cmake --build . +cp libflutter_elinux_eglstream.so ../../${OUTPUT_DIR}/${TARGET_ARCH}/debug +rm -rf * + +# Build eglstream (for release mode) +cp ${ABS_INSTALL_DIR}/libflutter_engine.so . +cmake $ARCH_ARGS -DBUILD_ELINUX_SO=ON -DBACKEND_TYPE=DRM-EGLSTREAM -DCMAKE_BUILD_TYPE=Release -DENABLE_ELINUX_EMBEDDER_LOG=OFF -DFLUTTER_RELEASE=ON .. +cmake --build . +cp libflutter_elinux_eglstream.so ../../${OUTPUT_DIR}/${TARGET_ARCH}/release +rm -rf * + +cd ../.. + +# Creates release packages +cd ${OUTPUT_DIR}/${TARGET_ARCH} +zip -jr embedder-${TARGET_ARCH}-debug.zip debug/* +zip -jr embedder-${TARGET_ARCH}-release.zip release/* +cd ../.. + +# Gathers common files +cp -rf flutter-embedded-linux/src/client_wrapper ${OUTPUT_DIR}/common +cp -rf flutter-embedded-linux/src/flutter/shell/platform/common/client_wrapper ${OUTPUT_DIR}/common +cp -rf flutter-embedded-linux/src/flutter/shell/platform/common/public/* ${OUTPUT_DIR}/common +cp -rf flutter-embedded-linux/src/flutter/shell/platform/linux_embedded/public/* ${OUTPUT_DIR}/common + +cd ${OUTPUT_DIR}/common +mv client_wrapper cpp_client_wrapper +zip -r embedder-common.zip * +cd ../.. + +echo "" +echo "Build completed successfully." +echo "Artifacts are in ${OUTPUT_DIR}/" diff --git a/release/build-flutter-engine.sh b/release/build-flutter-engine.sh new file mode 100755 index 00000000..82e83b37 --- /dev/null +++ b/release/build-flutter-engine.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +set -ex + +# Example) +# +#./build-flutter-engine.sh --revision=$(cat embedder.version) --arch=arm64 --build-dir=build-embedder +# + +BUILD_DIR=${BUILD_DIR:-"build-embedder"} +TARGET_ARCH=${TARGET_ARCH:-"x64"} +REVISION=${REVISION:-""} +OUTPUT_DIR="out" +REPO_URL=https://github.com/flutter/flutter.git + +for i; do + case $i in + --revision=*) + REVISION="${i#*=}" + ;; + --arch=*) + TARGET_ARCH="${i#*=}" + ;; + --build-dir=*) + BUILD_DIR="${i#*=}" + ;; + esac +done + + + +# check if need to build. +if [ -z "${REVISION}" ]; then + echo "Warning: No revision specified." +fi + +# Builds Flutter Engine + +install_depot_tools() { + # Get gclient + if [ ! -d depot_tools ]; then + git clone --filter blob:none https://chromium.googlesource.com/chromium/tools/depot_tools.git + fi + export PATH=$PATH:$(pwd)/depot_tools +} + +get_flutter_source() { + echo "Flutter Engine version: "${REVISION} + + # already checked out? + if [ -n "$REVISION" ] && [ "$(git -C flutter rev-parse HEAD "$REVISION" 2>/dev/null | uniq | wc -l)" = 1 ]; then + return + fi + + # Clone flutter repo + if [ ! -d flutter ]; then + git clone --filter blob:none ${REPO_URL} + elif [ -z "$REVISION" ] || ! git -C flutter rev-parse "$REVISION" 2>/dev/null; then + git -C flutter fetch + fi + + if [ -n "${REVISION}" ]; then + git -C flutter checkout "${REVISION}" + fi +} + +set_flutter_path() { + export PATH=$PATH:$(pwd)/flutter/engine/src/flutter/bin + + # patch: https://github.com/flutter/flutter/issues/163487 + export PATH=$(pwd)/flutter/engine/src/flutter/third_party/ninja:$PATH + export PATH=$(pwd)/flutter/engine/src/flutter/third_party/depot_tools/ninja:$PATH +} + +gclient_sync() { + # gclient sync + pushd flutter + + if [ -n "${REVISION}" ]; then + URL="${REPO_URL}@${REVISION}" + else + URL="${REPO_URL}" + fi + + if [ -e .gclient_sync_ok ] && grep -q "$URL" .gclient; then + popd + return + fi + + rm -f .gclient_sync_ok + cat < appropriately for your environment. +set(target_sysroot /) +set(CMAKE_SYSROOT ${target_sysroot}) + +# Specify the cross compiler. +set(triple aarch64-linux-gnu) +set(CMAKE_C_COMPILER_TARGET ${triple}) +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER_TARGET ${triple}) +set(CMAKE_CXX_COMPILER clang++) + +set(CMAKE_FIND_ROOT_PATH ${target_sysroot}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/release/get-flutter-versions.sh b/release/get-flutter-versions.sh new file mode 100755 index 00000000..df93af45 --- /dev/null +++ b/release/get-flutter-versions.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +set -ex + +CHANNEL=${CHANNEL:-"stable"} +BUILD_DIR=${BUILD_DIR:-"build-embedder"} + +for i; do + case $i in + --build-dir=*) + BUILD_DIR="${i#*=}" + ;; + --channel=*) + CHANNEL="${i#*=}" + ;; + --flutter-rev=*) + FLUTTER_REV="${i#*=}" + CHANNEL="" + ;; + *) + echo "bad option $1" + exit 1 + ;; + esac +done + +install_depot_tools() { + # Get gclient + if [ ! -d depot_tools ]; then + git clone --filter blob:none https://chromium.googlesource.com/chromium/tools/depot_tools.git + fi + export PATH="$PATH:$PWD/depot_tools" +} + +# required for git checkout in flutter repo +install_depot_tools + +mkdir -p "$BUILD_DIR" + +if [ -n "$CHANNEL" ]; then + [ -z "$FLUTTER_REV" ] || exit 1 + # Get flutter engine version + curl -OL "https://raw.githubusercontent.com/flutter/flutter/$CHANNEL/bin/internal/engine.version" + mv engine.version "$BUILD_DIR/embedder.version" + ENGINE_VERSION=$(cat "$BUILD_DIR/embedder.version") + + # Save channel + echo "$CHANNEL" > "$BUILD_DIR/embedder.channel" + + if [ -n "${USE_FLUTTER_SRC_CACHE}" ] && [ -d "$BUILD_DIR/flutter" ] ; then + echo "Using cached flutter source" + else + # Get flutter source code + if ! [ -d "$BUILD_DIR/flutter" ]; then + git clone --filter blob:none https://github.com/flutter/flutter.git "$BUILD_DIR/flutter" + elif ! git -C "$BUILD_DIR/flutter" rev-parse "$ENGINE_VERSION" 2>/dev/null; then + git -C "$BUILD_DIR/flutter" fetch + fi + git -C "$BUILD_DIR/flutter" checkout "$ENGINE_VERSION" + fi + + # Get SDK version + "$BUILD_DIR/flutter/bin/flutter" channel "$CHANNEL" + "$BUILD_DIR/flutter/bin/flutter" upgrade + "$BUILD_DIR/flutter/bin/flutter" --version > "$BUILD_DIR/sdk.version" + git -C "$BUILD_DIR/flutter" rev-parse HEAD > "$BUILD_DIR/flutter.version" + git -C "$BUILD_DIR/flutter" describe --tags >> "$BUILD_DIR/flutter.version" + +elif [ -n "$FLUTTER_REV" ]; then + + # Get flutter source code + if ! [ -d "$BUILD_DIR/flutter" ]; then + git clone --filter blob:none https://github.com/flutter/flutter.git "$BUILD_DIR/flutter" + elif ! git -C "$BUILD_DIR/flutter" rev-parse "$FLUTTER_REV" 2>/dev/null; then + git -C "$BUILD_DIR/flutter" fetch + fi + git -C "$BUILD_DIR/flutter" checkout "$FLUTTER_REV" + + echo "$FLUTTER_REV" > "$BUILD_DIR/flutter.version" + git -C "$BUILD_DIR/flutter" describe --tags >> "$BUILD_DIR/flutter.version" + cat "$BUILD_DIR/flutter/bin/internal/engine.version" > "$BUILD_DIR/embedder.version" + ENGINE_VERSION=$(cat "$BUILD_DIR/embedder.version") + echo user-branch > "$BUILD_DIR/embedder.channel" + + # run twice to fetch engine first (and not have fetch messages in sdk.version file) + "$BUILD_DIR/flutter/bin/flutter" --version + "$BUILD_DIR/flutter/bin/flutter" --version > "$BUILD_DIR/sdk.version" + # fix repo url + sed -i -e 's#unknown source#https://github.com/flutter/flutter.git#' "$BUILD_DIR/sdk.version" +else + echo "set either --channel or --engine" + exit 1 +fi + + +# Confirm version +SDK_VERSION=$(cat "$BUILD_DIR/sdk.version") +SHORT_VERSION=${ENGINE_VERSION:0:10} +if [[ ${SDK_VERSION} != *"${SHORT_VERSION}"* ]]; then + exit 1 +fi diff --git a/release/package-flutter-engine.sh b/release/package-flutter-engine.sh new file mode 100755 index 00000000..f7e2d8ef --- /dev/null +++ b/release/package-flutter-engine.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash + +set -ex + +# Example) +# +#./package-flutter-engine.sh --arch=arm64 --build-dir=build-embedder --artifact-dir=. --output-dir=$(pwd) +# + +BUILD_DIR=${BUILD_DIR:-"build-embedder"} +TARGET_ARCH=${TARGET_ARCH:-"x64"} +ARTIFACTS_PATH=${ARTIFACTS_PATH:-"."} +OUTPUT_DIR=${OUTPUT_DIR:-$(pwd)} + +for i; do + case $i in + --arch=*) + TARGET_ARCH="${i#*=}" + ;; + --build-dir=*) + BUILD_DIR="${i#*=}" + ;; + --artifact-dir=*) + ARTIFACTS_PATH="${i#*=}" + ;; + --output-dir=*) + OUTPUT_DIR="${i#*=}" + ;; + esac +done + +ENGINE_ROOT=${BUILD_DIR}/flutter/engine + +if [ ${TARGET_ARCH} = "arm64" ]; then + DEBUG_OUTDIR="linux_debug_unopt_arm64" + PROFILE_OUTDIR="linux_profile_arm64" + RELEASE_OUTDIR="linux_release_arm64" +else + DEBUG_OUTDIR="host_debug_unopt" + PROFILE_OUTDIR="host_profile" + RELEASE_OUTDIR="host_release" +fi + +## common +mkdir deploy_package +if [ ${TARGET_ARCH} = "x64" ]; then + mkdir deploy_package/icu + cp ${ENGINE_ROOT}/src/out/host_debug_unopt/icudtl.dat deploy_package/icu/ + unzip ${ARTIFACTS_PATH}/../common/embedder-common.zip -d deploy_package/ + + cd deploy_package + zip -r elinux-common.zip * + cd .. + mv deploy_package/elinux-common.zip ${OUTPUT_DIR} + rm -rf deploy_package/* +fi + + +## debug mode +cp ${ENGINE_ROOT}/src/out/${DEBUG_OUTDIR}/libflutter_engine.so deploy_package/ +unzip ${ARTIFACTS_PATH}/embedder-${TARGET_ARCH}-debug.zip -d deploy_package/ +zip -jr ${OUTPUT_DIR}/elinux-${TARGET_ARCH}-debug.zip deploy_package/* +rm -rf deploy_package/* + + +## profile mode +cp ${ENGINE_ROOT}/src/out/${PROFILE_OUTDIR}/libflutter_engine.so deploy_package/ +mkdir deploy_package/linux-x64 +if [ ${TARGET_ARCH} = "x64" ]; then + cp ${ENGINE_ROOT}/src/out/${PROFILE_OUTDIR}/gen_snapshot deploy_package/linux-x64/ +else + cp ${ENGINE_ROOT}/src/out/${PROFILE_OUTDIR}/clang_x64/gen_snapshot deploy_package/linux-x64/ +fi + +pushd deploy_package +zip -r elinux-${TARGET_ARCH}-profile.zip * +mv elinux-${TARGET_ARCH}-profile.zip ${OUTPUT_DIR} +popd + +rm -rf deploy_package/* + +## release mode +cp ${ENGINE_ROOT}/src/out/${RELEASE_OUTDIR}/libflutter_engine.so deploy_package/ +mkdir deploy_package/linux-x64 +if [ ${TARGET_ARCH} = "x64" ]; then + cp ${ENGINE_ROOT}/src/out/${RELEASE_OUTDIR}/gen_snapshot deploy_package/linux-x64/ +else + cp ${ENGINE_ROOT}/src/out/${RELEASE_OUTDIR}/clang_x64/gen_snapshot deploy_package/linux-x64/ +fi +unzip ${ARTIFACTS_PATH}/embedder-${TARGET_ARCH}-release.zip -d deploy_package/ + +pushd deploy_package +zip -r elinux-${TARGET_ARCH}-release.zip * +mv elinux-${TARGET_ARCH}-release.zip ${OUTPUT_DIR} +popd + + +rm -rf deploy_package diff --git a/release/prepare-release.sh b/release/prepare-release.sh new file mode 100755 index 00000000..be2b1e08 --- /dev/null +++ b/release/prepare-release.sh @@ -0,0 +1,81 @@ +#!/usr/bin/bash + +error() { + printf "%s\n" "$@" >&2 + exit 1 +} + +print_tag() { + local dir="$1" + + ( + cd "$dir" || exit + [ -e embedder.version ] || error "Missing embedder.version, not a release dir?" + [ -e elinux-arm64-debug.zip ] || error "release incomplete: missing elinux-arm64-debug.zip" + [ -e elinux-arm64-profile.zip ] || error "release incomplete: missing elinux-arm64-profile.zip" + [ -e elinux-arm64-release.zip ] || error "release incomplete: missing elinux-arm64-release.zip" + [ -e elinux-common.zip ] || error "release incomplete: missing elinux-common.zip" + [ -e elinux-x64-debug.zip ] || error "release incomplete: missing elinux-x64-debug.zip" + [ -e elinux-x64-profile.zip ] || error "release incomplete: missing elinux-x64-profile.zip" + [ -e elinux-x64-release.zip ] || error "release incomplete: missing elinux-x64-release.zip" + [ -e embedder.channel ] || error "release incomplete: missing embedder.channel" + [ -e flutter.version ] || error "release incomplete: missing flutter.version" + [ -e sdk.version ] || error "release incomplete: missing sdk.version" + + # check zip files content are sane-ish? not-empty, valid zips? + # For now manually check sizes are in the correct ballpark in below output.. + + ENGINE_VER=$(cat embedder.version) + TAG=${ENGINE_VER:0:10} + + cat < + namespace flutter { constexpr double kMegaByteSizeInBytes = (1 << 20); diff --git a/src/flutter/shell/platform/common/client_wrapper/include/flutter/binary_messenger.h b/src/flutter/shell/platform/common/client_wrapper/include/flutter/binary_messenger.h index d552b499..553ba0bb 100644 --- a/src/flutter/shell/platform/common/client_wrapper/include/flutter/binary_messenger.h +++ b/src/flutter/shell/platform/common/client_wrapper/include/flutter/binary_messenger.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BINARY_MESSENGER_H_ #define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BINARY_MESSENGER_H_ +#include #include #include diff --git a/src/flutter/shell/platform/common/client_wrapper/include/flutter/byte_streams.h b/src/flutter/shell/platform/common/client_wrapper/include/flutter/byte_streams.h index 3360bab9..8b413a45 100644 --- a/src/flutter/shell/platform/common/client_wrapper/include/flutter/byte_streams.h +++ b/src/flutter/shell/platform/common/client_wrapper/include/flutter/byte_streams.h @@ -5,6 +5,9 @@ #ifndef FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BYTE_STREAMS_H_ #define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BYTE_STREAMS_H_ +#include +#include + // Interfaces for interacting with a stream of bytes, for use in codecs. namespace flutter { diff --git a/src/flutter/shell/platform/common/client_wrapper/include/flutter/event_sink.h b/src/flutter/shell/platform/common/client_wrapper/include/flutter/event_sink.h index 789be1eb..f94ccce1 100644 --- a/src/flutter/shell/platform/common/client_wrapper/include/flutter/event_sink.h +++ b/src/flutter/shell/platform/common/client_wrapper/include/flutter/event_sink.h @@ -5,6 +5,9 @@ #ifndef FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_SINK_H_ #define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_SINK_H_ +#include +#include + namespace flutter { class EncodableValue; diff --git a/src/flutter/shell/platform/common/client_wrapper/include/flutter/event_stream_handler_functions.h b/src/flutter/shell/platform/common/client_wrapper/include/flutter/event_stream_handler_functions.h index fde4ce44..fe23e7e2 100644 --- a/src/flutter/shell/platform/common/client_wrapper/include/flutter/event_stream_handler_functions.h +++ b/src/flutter/shell/platform/common/client_wrapper/include/flutter/event_stream_handler_functions.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_STREAM_HANDLER_FUNCTIONS_H_ #define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_STREAM_HANDLER_FUNCTIONS_H_ +#include #include #include "event_sink.h" diff --git a/src/flutter/shell/platform/common/client_wrapper/include/flutter/message_codec.h b/src/flutter/shell/platform/common/client_wrapper/include/flutter/message_codec.h index c84d25f2..0bd0287e 100644 --- a/src/flutter/shell/platform/common/client_wrapper/include/flutter/message_codec.h +++ b/src/flutter/shell/platform/common/client_wrapper/include/flutter/message_codec.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_MESSAGE_CODEC_H_ #define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_MESSAGE_CODEC_H_ +#include #include #include #include diff --git a/src/flutter/shell/platform/common/client_wrapper/include/flutter/method_codec.h b/src/flutter/shell/platform/common/client_wrapper/include/flutter/method_codec.h index b40fa640..0721367e 100644 --- a/src/flutter/shell/platform/common/client_wrapper/include/flutter/method_codec.h +++ b/src/flutter/shell/platform/common/client_wrapper/include/flutter/method_codec.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CODEC_H_ #define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CODEC_H_ +#include #include #include #include diff --git a/src/flutter/shell/platform/linux_embedded/flutter_elinux.cc b/src/flutter/shell/platform/linux_embedded/flutter_elinux.cc index 2d3587f3..f5795f3f 100644 --- a/src/flutter/shell/platform/linux_embedded/flutter_elinux.cc +++ b/src/flutter/shell/platform/linux_embedded/flutter_elinux.cc @@ -95,7 +95,10 @@ FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate( // Take ownership of the engine, starting it if necessary. state->view->SetEngine( std::unique_ptr(EngineFromHandle(engine))); - state->view->CreateRenderSurface(); + if (!state->view->CreateRenderSurface()) { + return nullptr; + } + if (!state->view->GetEngine()->running()) { if (!state->view->GetEngine()->RunWithEntrypoint(nullptr)) { return nullptr; diff --git a/src/flutter/shell/platform/linux_embedded/plugins/text_input_plugin.cc b/src/flutter/shell/platform/linux_embedded/plugins/text_input_plugin.cc index 3cc932c9..8eee76ea 100644 --- a/src/flutter/shell/platform/linux_embedded/plugins/text_input_plugin.cc +++ b/src/flutter/shell/platform/linux_embedded/plugins/text_input_plugin.cc @@ -117,9 +117,9 @@ void TextInputPlugin::HandleMethodCall( const std::string& method = method_call.method_name(); if (method.compare(kShowMethod) == 0) { - delegate_->UpdateVirtualKeyboardStatus(true); + delegate_->UpdateVirtualKeyboardStatus(true, input_type_); } else if (method.compare(kHideMethod) == 0) { - delegate_->UpdateVirtualKeyboardStatus(false); + delegate_->UpdateVirtualKeyboardStatus(false, input_type_); } else if (method.compare(kClearClientMethod) == 0) { active_model_ = nullptr; } else if (method.compare(kSetClientMethod) == 0) { diff --git a/src/flutter/shell/platform/linux_embedded/public/flutter_platform_views.h b/src/flutter/shell/platform/linux_embedded/public/flutter_platform_views.h index 0e7c9d52..d67a6147 100644 --- a/src/flutter/shell/platform/linux_embedded/public/flutter_platform_views.h +++ b/src/flutter/shell/platform/linux_embedded/public/flutter_platform_views.h @@ -5,9 +5,8 @@ #ifndef FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_PUBLIC_FLUTTER_PLATFORM_VIEWS_H_ #define FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_PUBLIC_FLUTTER_PLATFORM_VIEWS_H_ -#include -#include - +#include +#include #include #include diff --git a/src/flutter/shell/platform/linux_embedded/surface/cursor_data.h b/src/flutter/shell/platform/linux_embedded/surface/cursor_data.h index 4a7f6663..c2089735 100644 --- a/src/flutter/shell/platform/linux_embedded/surface/cursor_data.h +++ b/src/flutter/shell/platform/linux_embedded/surface/cursor_data.h @@ -28,6 +28,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_SURFACE_CURSOR_DATA_H_ #define FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_SURFACE_CURSOR_DATA_H_ +#include #include namespace flutter { @@ -2326,4 +2327,4 @@ const std::unordered_map> } // namespace flutter -#endif // FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_SURFACE_CURSOR_DATA_H_ \ No newline at end of file +#endif // FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_SURFACE_CURSOR_DATA_H_ diff --git a/src/flutter/shell/platform/linux_embedded/surface/elinux_egl_surface.cc b/src/flutter/shell/platform/linux_embedded/surface/elinux_egl_surface.cc index 914ab736..cee23938 100644 --- a/src/flutter/shell/platform/linux_embedded/surface/elinux_egl_surface.cc +++ b/src/flutter/shell/platform/linux_embedded/surface/elinux_egl_surface.cc @@ -166,6 +166,15 @@ void ELinuxEGLSurface::PopulateExistingDamage(const intptr_t fbo_id, existing_damage->num_rects = 1; + // Free any previous allocation for this FBO (defensive: guards against the + // engine calling populate without a subsequent present_with_info, which would + // otherwise orphan the malloc'd buffer). + auto it = existing_damage_map_.find(fbo_id); + if (it != existing_damage_map_.end() && it->second != nullptr) { + free(it->second); + it->second = nullptr; + } + // Allocate the array of rectangles for the existing damage. existing_damage_map_[fbo_id] = static_cast( malloc(sizeof(FlutterRect) * existing_damage->num_rects)); diff --git a/src/flutter/shell/platform/linux_embedded/surface/environment_egl.h b/src/flutter/shell/platform/linux_embedded/surface/environment_egl.h index 83d94472..1abacee0 100644 --- a/src/flutter/shell/platform/linux_embedded/surface/environment_egl.h +++ b/src/flutter/shell/platform/linux_embedded/surface/environment_egl.h @@ -6,6 +6,7 @@ #define FLUTTER_SHELL_PLATFORM_LINUX_EMBEDDED_SURFACE_ENVIRONMENT_EGL_H_ #include +#include #include "flutter/shell/platform/linux_embedded/logger.h" #include "flutter/shell/platform/linux_embedded/surface/egl_utils.h" @@ -14,10 +15,25 @@ namespace flutter { class EnvironmentEgl { public: - EnvironmentEgl(EGLNativeDisplayType platform_display, + EnvironmentEgl(EGLenum platform, + EGLNativeDisplayType platform_display, bool sub_environment = false) : display_(EGL_NO_DISPLAY), sub_environment_(sub_environment) { - display_ = eglGetDisplay(platform_display); + if (platform) { + auto client_exts = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (client_exts && + has_egl_extension(client_exts, "EGL_EXT_platform_base")) { + auto get_platform_display = + reinterpret_cast( + eglGetProcAddress("eglGetPlatformDisplayEXT")); + if (get_platform_display) { + display_ = get_platform_display(platform, platform_display, nullptr); + } + } + } + if (display_ == EGL_NO_DISPLAY) { + display_ = eglGetDisplay(platform_display); + } if (display_ == EGL_NO_DISPLAY) { ELINUX_LOG(ERROR) << "Failed to get the EGL display: " << get_egl_error_cause(); diff --git a/src/flutter/shell/platform/linux_embedded/window/elinux_window.h b/src/flutter/shell/platform/linux_embedded/window/elinux_window.h index e9b6bf66..dc8468a8 100644 --- a/src/flutter/shell/platform/linux_embedded/window/elinux_window.h +++ b/src/flutter/shell/platform/linux_embedded/window/elinux_window.h @@ -45,7 +45,7 @@ class ELinuxWindow { void NotifyDisplayInfoUpdates() const { if (binding_handler_delegate_) { binding_handler_delegate_->UpdateDisplayInfo( - std::trunc(1000000.0 / frame_rate_), GetCurrentWidth(), + static_cast(frame_rate_) / 1000.0, GetCurrentWidth(), GetCurrentHeight(), current_scale_); } } diff --git a/src/flutter/shell/platform/linux_embedded/window/elinux_window_drm.h b/src/flutter/shell/platform/linux_embedded/window/elinux_window_drm.h index fa1fb9e9..d5447061 100644 --- a/src/flutter/shell/platform/linux_embedded/window/elinux_window_drm.h +++ b/src/flutter/shell/platform/linux_embedded/window/elinux_window_drm.h @@ -17,6 +17,7 @@ #endif #include +#include #include #include #include @@ -197,8 +198,8 @@ class ELinuxWindowDrm : public ELinuxWindow, public WindowBindingHandler { << "Normal mode is not supported, use fullscreen mode."; view_properties_.view_mode = FlutterDesktopViewMode::kFullscreen; } - view_properties_.width = native_window_->Width(); - view_properties_.height = native_window_->Height(); + view_properties_.width = native_window_->Width() / current_scale_; + view_properties_.height = native_window_->Height() / current_scale_; ELINUX_LOG(INFO) << "Display output resolution: " << view_properties_.width << "x" << view_properties_.height; @@ -249,7 +250,9 @@ class ELinuxWindowDrm : public ELinuxWindow, public WindowBindingHandler { } // |FlutterWindowBindingHandler| - void UpdateVirtualKeyboardStatus(const bool show) override { + void UpdateVirtualKeyboardStatus( + const bool show, + const std::string& input_type = "") override { // currently not supported. } @@ -393,8 +396,8 @@ class ELinuxWindowDrm : public ELinuxWindow, public WindowBindingHandler { } if (self->view_properties_.width != width || self->view_properties_.height != height) { - self->view_properties_.width = width; - self->view_properties_.height = height; + self->view_properties_.width = width / self->current_scale_; + self->view_properties_.height = height / self->current_scale_; ELINUX_LOG(INFO) << "Display output resolution: " << self->view_properties_.width << "x" << self->view_properties_.height; @@ -565,8 +568,8 @@ class ELinuxWindowDrm : public ELinuxWindow, public WindowBindingHandler { void OnPointerMotion(libinput_event* event) { DetectPointerDevice(event); if (binding_handler_delegate_) { - auto width = view_properties_.width; - auto height = view_properties_.height; + auto width = GetCurrentWidth(); + auto height = GetCurrentHeight(); if (current_rotation_ == 90 || current_rotation_ == 270) { std::swap(width, height); } @@ -589,8 +592,8 @@ class ELinuxWindowDrm : public ELinuxWindow, public WindowBindingHandler { } void OnPointerMotionAbsolute(libinput_event* event) { - auto width = view_properties_.width; - auto height = view_properties_.height; + auto width = GetCurrentWidth(); + auto height = GetCurrentHeight(); if (current_rotation_ == 90 || current_rotation_ == 270) { std::swap(width, height); } @@ -693,8 +696,8 @@ class ELinuxWindowDrm : public ELinuxWindow, public WindowBindingHandler { void OnTouchDown(libinput_event* event) { if (binding_handler_delegate_) { - auto width = view_properties_.width; - auto height = view_properties_.height; + auto width = GetCurrentWidth(); + auto height = GetCurrentHeight(); if (current_rotation_ == 90 || current_rotation_ == 270) { std::swap(width, height); } @@ -719,8 +722,8 @@ class ELinuxWindowDrm : public ELinuxWindow, public WindowBindingHandler { void OnTouchMotion(libinput_event* event) { if (binding_handler_delegate_) { - auto width = view_properties_.width; - auto height = view_properties_.height; + auto width = GetCurrentWidth(); + auto height = GetCurrentHeight(); if (current_rotation_ == 90 || current_rotation_ == 270) { std::swap(width, height); } diff --git a/src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.cc b/src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.cc index 6467bf94..4a5abbbf 100644 --- a/src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.cc +++ b/src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.cc @@ -269,6 +269,7 @@ const wl_callback_listener ELinuxWindowWayland::kWlSurfaceFrameListener = { // by all compositors. This path is for when it wasn't supported. auto self = reinterpret_cast(data); if (self->wp_presentation_clk_id_ != UINT32_MAX) { + wl_callback_destroy(wl_callback); return; } @@ -299,7 +300,12 @@ const wl_seat_listener ELinuxWindowWayland::kWlSeatListener = { if ((caps & WL_SEAT_CAPABILITY_POINTER) && !inputs.pointer) { inputs.pointer = wl_seat_get_pointer(seat); wl_pointer_add_listener(inputs.pointer, &kWlPointerListener, self); + ELINUX_LOG(TRACE) << "Pointer device connected: " << inputs.pointer; } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && inputs.pointer) { + ELINUX_LOG(TRACE) << "Pointer device disconnecting: " << inputs.pointer; + if (self->cursor_info_.pointer == inputs.pointer) { + self->cursor_info_.pointer = nullptr; + } wl_pointer_release(inputs.pointer); inputs.pointer = nullptr; } @@ -1068,6 +1074,7 @@ ELinuxWindowWayland::ELinuxWindowWayland( wl_data_offer_(nullptr), wl_data_source_(nullptr), serial_(0), + text_input_serial_(0), zwp_text_input_manager_v1_(nullptr), zwp_text_input_manager_v3_(nullptr), zwp_text_input_v1_(nullptr), @@ -1443,7 +1450,8 @@ bool ELinuxWindowWayland::CreateRenderSurface(int32_t width_px, wl_surface_commit(native_window_->Surface()); render_surface_ = std::make_unique(std::make_unique( - std::make_unique(wl_display_), enable_impeller)); + std::make_unique(EGL_PLATFORM_WAYLAND_KHR, wl_display_), + enable_impeller)); render_surface_->SetNativeWindow(native_window_.get()); if (view_properties_.use_window_decoration) { @@ -1505,12 +1513,15 @@ void ELinuxWindowWayland::DestroyRenderSurface() { } } -void ELinuxWindowWayland::UpdateVirtualKeyboardStatus(const bool show) { +void ELinuxWindowWayland::UpdateVirtualKeyboardStatus( + const bool show, + const std::string& input_type) { // Not supported virtual keyboard. if (!(zwp_text_input_v1_ || zwp_text_input_v3_) || seat_inputs_map_.empty()) { return; } + text_input_type_ = input_type; is_requested_show_virtual_keyboard_ = show; if (is_requested_show_virtual_keyboard_) { ShowVirtualKeyboard(); @@ -1521,6 +1532,9 @@ void ELinuxWindowWayland::UpdateVirtualKeyboardStatus(const bool show) { void ELinuxWindowWayland::UpdateFlutterCursor(const std::string& cursor_name) { if (view_properties_.use_mouse_cursor) { + if (!cursor_info_.pointer) { + return; + } if (cursor_name.compare(cursor_info_.cursor_name) == 0) { return; } @@ -1869,16 +1883,53 @@ void ELinuxWindowWayland::ShowVirtualKeyboard() { zwp_text_input_v3_enable(zwp_text_input_v3_); zwp_text_input_v3_commit(zwp_text_input_v3_); - zwp_text_input_v3_set_content_type( - zwp_text_input_v3_, ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, - ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL); + // Map Flutter input types to Wayland content purposes. + uint32_t hint = ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE; + uint32_t purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL; + + if (text_input_type_ == "TextInputType.number") { + purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER; + } else if (text_input_type_ == "TextInputType.phone") { + purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE; + } else if (text_input_type_ == "TextInputType.emailAddress") { + purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL; + } else if (text_input_type_ == "TextInputType.url") { + purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL; + } else if (text_input_type_ == "TextInputType.visiblePassword") { + purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD; + } else if (text_input_type_ == "TextInputType.multiline") { + hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_MULTILINE; + } + + zwp_text_input_v3_set_content_type(zwp_text_input_v3_, hint, + purpose); // Untested code path zwp_text_input_v3_commit(zwp_text_input_v3_); } else { if (native_window_) { - zwp_text_input_v1_show_input_panel(zwp_text_input_v1_); + // Map Flutter input types to Wayland v1 content purposes. + uint32_t hint = ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE; + uint32_t purpose = ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NORMAL; + + if (text_input_type_ == "TextInputType.number") { + purpose = ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER; + } else if (text_input_type_ == "TextInputType.phone") { + purpose = ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PHONE; + } else if (text_input_type_ == "TextInputType.emailAddress") { + purpose = ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_EMAIL; + } else if (text_input_type_ == "TextInputType.url") { + purpose = ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL; + } else if (text_input_type_ == "TextInputType.visiblePassword") { + purpose = ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD; + } else if (text_input_type_ == "TextInputType.multiline") { + hint |= ZWP_TEXT_INPUT_V1_CONTENT_HINT_MULTILINE; + } + zwp_text_input_v1_activate(zwp_text_input_v1_, seat_inputs_map_.begin()->first, native_window_->Surface()); + zwp_text_input_v1_set_content_type(zwp_text_input_v1_, hint, purpose); + zwp_text_input_v1_commit_state(zwp_text_input_v1_, ++text_input_serial_); + zwp_text_input_v1_show_input_panel(zwp_text_input_v1_); } } } diff --git a/src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.h b/src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.h index 8ccb84ba..ec8dce63 100644 --- a/src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.h +++ b/src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.h @@ -82,7 +82,8 @@ class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler { void UpdateFlutterCursor(const std::string& cursor_name) override; // |FlutterWindowBindingHandler| - void UpdateVirtualKeyboardStatus(const bool show) override; + void UpdateVirtualKeyboardStatus(const bool show, + const std::string& input_type = "") override; // |FlutterWindowBindingHandler| std::string GetClipboardData() override; @@ -215,6 +216,11 @@ class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler { wl_data_source* wl_data_source_; uint32_t wl_data_device_manager_version_; uint32_t serial_; + + // The current text input type (e.g., "TextInputType.number"). + std::string text_input_type_; + + uint32_t text_input_serial_; }; } // namespace flutter diff --git a/src/flutter/shell/platform/linux_embedded/window/elinux_window_x11.cc b/src/flutter/shell/platform/linux_embedded/window/elinux_window_x11.cc index 862c4d64..1ee20edb 100644 --- a/src/flutter/shell/platform/linux_embedded/window/elinux_window_x11.cc +++ b/src/flutter/shell/platform/linux_embedded/window/elinux_window_x11.cc @@ -125,7 +125,8 @@ bool ELinuxWindowX11::CreateRenderSurface(int32_t width, int32_t height, bool enable_impeller) { auto context_egl = std::make_unique( - std::make_unique(display_), enable_impeller); + std::make_unique(EGL_PLATFORM_X11_KHR, display_), + enable_impeller); if (current_rotation_ == 90 || current_rotation_ == 270) { std::swap(width, height); @@ -179,7 +180,9 @@ void ELinuxWindowX11::UpdateFlutterCursor(const std::string& cursor_name) { // TODO: implement here } -void ELinuxWindowX11::UpdateVirtualKeyboardStatus(const bool show) { +void ELinuxWindowX11::UpdateVirtualKeyboardStatus( + const bool show, + const std::string& input_type) { // currently not supported. } diff --git a/src/flutter/shell/platform/linux_embedded/window/elinux_window_x11.h b/src/flutter/shell/platform/linux_embedded/window/elinux_window_x11.h index eb11171e..42ec5ad0 100644 --- a/src/flutter/shell/platform/linux_embedded/window/elinux_window_x11.h +++ b/src/flutter/shell/platform/linux_embedded/window/elinux_window_x11.h @@ -55,7 +55,8 @@ class ELinuxWindowX11 : public ELinuxWindow, public WindowBindingHandler { void UpdateFlutterCursor(const std::string& cursor_name) override; // |FlutterWindowBindingHandler| - void UpdateVirtualKeyboardStatus(const bool show) override; + void UpdateVirtualKeyboardStatus(const bool show, + const std::string& input_type = "") override; // |FlutterWindowBindingHandler| std::string GetClipboardData() override; diff --git a/src/flutter/shell/platform/linux_embedded/window/native_window_drm.cc b/src/flutter/shell/platform/linux_embedded/window/native_window_drm.cc index 73023fd2..304b1302 100644 --- a/src/flutter/shell/platform/linux_embedded/window/native_window_drm.cc +++ b/src/flutter/shell/platform/linux_embedded/window/native_window_drm.cc @@ -13,6 +13,13 @@ #include "flutter/shell/platform/linux_embedded/logger.h" #include "flutter/shell/platform/linux_embedded/surface/cursor_data.h" +// Allow building with mesa < 21 +// This is a linux uapi header value so there is no risk in hardcoding it if +// unset +#ifndef DRM_MODE_CONNECTOR_USB +#define DRM_MODE_CONNECTOR_USB 20 +#endif + namespace flutter { namespace { constexpr char kFlutterDrmConnectorEnvironmentKey[] = "FLUTTER_DRM_CONNECTOR"; diff --git a/src/flutter/shell/platform/linux_embedded/window/native_window_drm_gbm.cc b/src/flutter/shell/platform/linux_embedded/window/native_window_drm_gbm.cc index 4565fcb8..59a651f7 100644 --- a/src/flutter/shell/platform/linux_embedded/window/native_window_drm_gbm.cc +++ b/src/flutter/shell/platform/linux_embedded/window/native_window_drm_gbm.cc @@ -134,7 +134,8 @@ bool NativeWindowDrmGbm::DismissCursor() { std::unique_ptr NativeWindowDrmGbm::CreateRenderSurface( bool enable_impeller) { return std::make_unique(std::make_unique( - std::make_unique(gbm_device_), enable_impeller)); + std::make_unique(EGL_PLATFORM_GBM_KHR, gbm_device_), + enable_impeller)); } bool NativeWindowDrmGbm::IsNeedRecreateSurfaceAfterResize() const { diff --git a/src/flutter/shell/platform/linux_embedded/window/renderer/window_decorations_wayland.cc b/src/flutter/shell/platform/linux_embedded/window/renderer/window_decorations_wayland.cc index b6c63c3b..8b1a275e 100644 --- a/src/flutter/shell/platform/linux_embedded/window/renderer/window_decorations_wayland.cc +++ b/src/flutter/shell/platform/linux_embedded/window/renderer/window_decorations_wayland.cc @@ -35,7 +35,8 @@ WindowDecorationsWayland::WindowDecorationsWayland( compositor, subcompositor, root_surface, width_dip * pixel_ratio, kTitleBarHeightDIP * pixel_ratio, enable_vsync), std::make_unique(std::make_unique( - std::make_unique(display, sub_egl_display), + std::make_unique(EGL_PLATFORM_WAYLAND_KHR, display, + sub_egl_display), enable_impeller))); titlebar_->SetPosition(0, -kTitleBarHeightDIP); @@ -48,7 +49,8 @@ WindowDecorationsWayland::WindowDecorationsWayland( kButtonWidthDIP * pixel_ratio, kButtonHeightDIP * pixel_ratio, enable_vsync), std::make_unique(std::make_unique( - std::make_unique(display, sub_egl_display), + std::make_unique(EGL_PLATFORM_WAYLAND_KHR, display, + sub_egl_display), enable_impeller)))); buttons_[type]->SetPosition( width_dip * pixel_ratio - kButtonWidthDIP - kButtonMarginDIP, @@ -63,7 +65,8 @@ WindowDecorationsWayland::WindowDecorationsWayland( kButtonWidthDIP * pixel_ratio, kButtonHeightDIP * pixel_ratio, enable_vsync), std::make_unique(std::make_unique( - std::make_unique(display, sub_egl_display), + std::make_unique(EGL_PLATFORM_WAYLAND_KHR, display, + sub_egl_display), enable_impeller)))); buttons_[type]->SetPosition( width_dip * pixel_ratio - kButtonWidthDIP * 2 - kButtonMarginDIP * 2, @@ -78,7 +81,8 @@ WindowDecorationsWayland::WindowDecorationsWayland( kButtonWidthDIP * pixel_ratio, kButtonHeightDIP * pixel_ratio, enable_vsync), std::make_unique(std::make_unique( - std::make_unique(display, sub_egl_display), + std::make_unique(EGL_PLATFORM_WAYLAND_KHR, display, + sub_egl_display), enable_impeller)))); buttons_[type]->SetPosition( width_dip * pixel_ratio - kButtonWidthDIP * 3 - kButtonMarginDIP * 3, diff --git a/src/flutter/shell/platform/linux_embedded/window_binding_handler.h b/src/flutter/shell/platform/linux_embedded/window_binding_handler.h index 34499df8..0a2847b2 100644 --- a/src/flutter/shell/platform/linux_embedded/window_binding_handler.h +++ b/src/flutter/shell/platform/linux_embedded/window_binding_handler.h @@ -70,7 +70,12 @@ class WindowBindingHandler { // Sets the virtual keyboard status when the virtual keyboard needs to be // shown by Flutter events. - virtual void UpdateVirtualKeyboardStatus(const bool show) = 0; + // @param[in] show Whether to show or hide the virtual keyboard. + // @param[in] input_type The Flutter input type (e.g., + // "TextInputType.number"). + virtual void UpdateVirtualKeyboardStatus( + const bool show, + const std::string& input_type = "") = 0; // Returns the clipboard data. virtual std::string GetClipboardData() = 0;