From f9449af87a4f5420aa7683d3f15110bfa2f1bf17 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 29 Oct 2022 18:22:35 +0100 Subject: [PATCH] kaios: Major parts of a build for KaiOS KaiOS (which is based on Firefox OS, formerly Boot to Gecko) runs its "native" apps in a Web browser, so this is essentially a rather specialised version of the JavaScript front-end. Indeed, the JavaScript and C parts are the same as the Web version. There are three major parts that are specific to the KaiOS build. First, there's manifest.pl, which generates a KaiOS-specific JSON manifest describing each puzzle. Second, there's a new HTML page generator, apppage.pl, that generates an HTML page that is much less like a Web page, and much more like an application, than the one generated by jspage.pl. It expects to build a single HTML page at a time and gets all its limited knowledge of the environment from its command line. This makes it gratuitously different from jspage.pl and javapage.pl, but makes it easier to run from the build system. And finally, there's the CMake glue that assembles the necessary parts for each application in a directory. This includes the manifest, the HTML, the JavaScript, the KaiOS-specific icons (generated as part of the GTK build) and a copy of the HTML documentation. The directory is assembled using CMake's install() function, and can be installed on a KaiOS device using the developer tools. --- cmake/platforms/emscripten.cmake | 67 ++++++ emccpre.js | 10 +- kaios/apppage.pl | 337 +++++++++++++++++++++++++++++++ kaios/manifest.pl | 36 ++++ 4 files changed, 449 insertions(+), 1 deletion(-) create mode 100755 kaios/apppage.pl create mode 100755 kaios/manifest.pl diff --git a/cmake/platforms/emscripten.cmake b/cmake/platforms/emscripten.cmake index 244cfcb..3cbcab4 100644 --- a/cmake/platforms/emscripten.cmake +++ b/cmake/platforms/emscripten.cmake @@ -6,6 +6,11 @@ set(CMAKE_EXECUTABLE_SUFFIX ".js") set(WASM ON CACHE BOOL "Compile to WebAssembly rather than plain JavaScript") +find_program(HALIBUT halibut) +if(NOT HALIBUT) + message(WARNING "HTML documentation cannot be built (did not find halibut)") +endif() + set(emcc_export_list # Event handlers for mouse and keyboard input _mouseup @@ -62,4 +67,66 @@ function(set_platform_puzzle_target_properties NAME TARGET) endfunction() function(build_platform_extras) + if(HALIBUT) + set(help_dir ${CMAKE_CURRENT_BINARY_DIR}/help) + add_custom_command(OUTPUT ${help_dir}/en + COMMAND ${CMAKE_COMMAND} -E make_directory ${help_dir}/en) + add_custom_command(OUTPUT ${help_dir}/en/index.html + COMMAND ${HALIBUT} --html -Chtml-template-fragment:%k + ${CMAKE_CURRENT_SOURCE_DIR}/puzzles.but + DEPENDS + ${help_dir}/en + ${CMAKE_CURRENT_SOURCE_DIR}/puzzles.but + WORKING_DIRECTORY ${help_dir}/en) + add_custom_target(kaios_help ALL + DEPENDS ${help_dir}/en/index.html) + endif() + + # This is probably not the right way to set the destination. + set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH + "Installation path" FORCE) + + add_custom_target(kaios-extras ALL) + + foreach(name ${puzzle_names}) + add_custom_command( + OUTPUT ${name}-manifest.webapp + COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/kaios/manifest.pl + "${name}" "${displayname_${name}}" "${description_${name}}" + "${objective_${name}}" > "${name}-manifest.webapp" + VERBATIM + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/kaios/manifest.pl) + + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/kaios) + add_custom_command( + OUTPUT ${name}-kaios.html + COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/kaios/apppage.pl + "${name}" "${displayname_${name}}" > "${name}-kaios.html" + VERBATIM + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/kaios/apppage.pl) + + add_custom_target(${name}-kaios-extras + DEPENDS ${name}-manifest.webapp ${name}-kaios.html) + add_dependencies(kaios-extras ${name}-kaios-extras) + + install(TARGETS ${name} DESTINATION kaios/${name}) + # Release builds generate an initial memory image alongside the + # JavaScript, but CMake doesn't seem to know about it to install + # it. + install(FILES $.mem OPTIONAL + DESTINATION kaios/${name}) + install(FILES ${ICON_DIR}/${name}-56kai.png ${ICON_DIR}/${name}-112kai.png + DESTINATION kaios/${name} OPTIONAL) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}-kaios.html + RENAME ${name}.html + DESTINATION kaios/${name}) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}-manifest.webapp + RENAME manifest.webapp + DESTINATION kaios/${name}) + if (HALIBUT) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/help + DESTINATION kaios/${name}) + endif() + + endforeach() endfunction() diff --git a/emccpre.js b/emccpre.js index 2bbaa57..f0169ec 100644 --- a/emccpre.js +++ b/emccpre.js @@ -534,6 +534,14 @@ function initPuzzle() { } menuform.addEventListener("keydown", menukey); + // Open documentation links within the application in KaiOS. + for (var elem of document.querySelectorAll("#gamemenu a[href]")) { + elem.addEventListener("click", function(event) { + window.open(event.target.href); + event.preventDefault(); + }); + } + // In IE, the canvas doesn't automatically gain focus on a mouse // click, so make sure it does onscreen_canvas.addEventListener("mousedown", function(event) { @@ -567,7 +575,7 @@ function initPuzzle() { event.preventDefault(); event.stopPropagation(); } - }, true); + }); // Event handler to fake :focus-within on browsers too old for // it (like KaiOS 2.5). Browsers without :focus-within are also diff --git a/kaios/apppage.pl b/kaios/apppage.pl new file mode 100755 index 0000000..ecdffbc --- /dev/null +++ b/kaios/apppage.pl @@ -0,0 +1,337 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +@ARGV == 2 or die "usage: apppage.pl "; +my ($name, $displayname) = @ARGV; + +print < + + + + +${displayname} + + + + + + +
+
+ + +
+
+
+
Menu
+
+
+
    +
  • Game
      +
    • +
    • +
    • +
    • +
  • +
  • Type
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • + Instructions +
    • +
    • + Full manual +
    • +
    +
    +
    Select
    +
    Dismiss
    +
    +
    + + +EOF diff --git a/kaios/manifest.pl b/kaios/manifest.pl new file mode 100755 index 0000000..36fc195 --- /dev/null +++ b/kaios/manifest.pl @@ -0,0 +1,36 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use JSON::PP; + +@ARGV == 4 or + die "usage: manifest.pl "; +my ($name, $displayname, $description, $objective) = @ARGV; + +# Limits from +# https://developer.kaiostech.com/docs/getting-started/main-concepts/manifest +length($displayname) <= 20 or die "Name too long: $displayname"; +length($description) <= 40 or die "Subtitle too long: $description"; +$objective .= " Part of Simon Tatham's Portable Puzzle Collection."; +# https://developer.kaiostech.com/docs/distribution/submission-guideline +length($objective) <= 220 or die "Description too long: $objective"; + +print encode_json({ + name => $displayname, + subtitle => $description, + description => $objective, + launch_path => "/${name}.html", + icons => { + "56" => "/${name}-56kai.png", + "112" => "/${name}-112kai.png", + }, + developer => { + name => "Ben Harris", + url => "https://bjh21.me.uk", + }, + default_locale => "en-GB", + categories => ["games"], + cursor => JSON::PP::false, +})