From bb9b64af8112fbf590e0619cea53ea00df7ec6d8 Mon Sep 17 00:00:00 2001 From: Joseph Cloutier Date: Sat, 11 Jun 2022 20:28:41 -0400 Subject: [PATCH 01/29] Suppress `uiMode` configuration changes. When the user switches between dark and light themes, Android destroys and recreates the activity. However, Lime activities can't be recreated like this, and just close instead. Since we don't actually use the system theme, there's no reason to do this. Simplest solution is to suppress it. https://developer.android.com/guide/topics/resources/runtime-changes https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#config-changes --- templates/android/template/app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/android/template/app/src/main/AndroidManifest.xml b/templates/android/template/app/src/main/AndroidManifest.xml index 22bb94f94..729e80391 100644 --- a/templates/android/template/app/src/main/AndroidManifest.xml +++ b/templates/android/template/app/src/main/AndroidManifest.xml @@ -19,7 +19,7 @@ ::end:: - + From 4e1974fc9ffc4edfefe61f4527cea0bb5058fd09 Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Tue, 14 Jun 2022 07:07:09 -0700 Subject: [PATCH 02/29] ManifestResources: if disable_preloader_assets is defined, keep the public API available Ensures that existing custom templates still work --- templates/haxe/ManifestResources.hx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/templates/haxe/ManifestResources.hx b/templates/haxe/ManifestResources.hx index a49c845f6..214de9ce0 100644 --- a/templates/haxe/ManifestResources.hx +++ b/templates/haxe/ManifestResources.hx @@ -1,7 +1,5 @@ -#if !disable_preloader_assets package; - import haxe.io.Bytes; import lime.utils.AssetBundle; import lime.utils.AssetLibrary; @@ -12,6 +10,18 @@ import lime.utils.Assets; import sys.FileSystem; #end +#if disable_preloader_assets +@:dox(hide) class ManifestResources { + public static var preloadLibraries:Array; + public static var preloadLibraryNames:Array; + public static var rootPath:String; + + public static function init (config:Dynamic):Void { + preloadLibraries = new Array (); + preloadLibraryNames = new Array (); + } +} +#else @:access(lime.utils.Assets) From e3a755ff60679c69ee59a05a04b5e7beff1f11a5 Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Tue, 14 Jun 2022 07:41:50 -0700 Subject: [PATCH 03/29] ManifestResources: use Dynamic instead of AssetLibrary when disable_preloader_assets is defined --- templates/haxe/ManifestResources.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/haxe/ManifestResources.hx b/templates/haxe/ManifestResources.hx index 214de9ce0..d8565bcde 100644 --- a/templates/haxe/ManifestResources.hx +++ b/templates/haxe/ManifestResources.hx @@ -12,7 +12,7 @@ import sys.FileSystem; #if disable_preloader_assets @:dox(hide) class ManifestResources { - public static var preloadLibraries:Array; + public static var preloadLibraries:Array; public static var preloadLibraryNames:Array; public static var rootPath:String; From 33502b099ec83a82c3630cb869601ca3f90680df Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Tue, 14 Jun 2022 07:42:30 -0700 Subject: [PATCH 04/29] Preloader: if disable_preloader_assets is defined, keep the public API available Ensures that existing custom templates still work --- src/lime/utils/Preloader.hx | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/lime/utils/Preloader.hx b/src/lime/utils/Preloader.hx index 2e803203d..3ff44761f 100644 --- a/src/lime/utils/Preloader.hx +++ b/src/lime/utils/Preloader.hx @@ -35,18 +35,14 @@ class Preloader #if flash extends Sprite #end public var onProgress = new EventInt->Void>(); @:noCompletion private var bytesLoaded:Int; - #if !disable_preloader_assets - @:noCompletion private var bytesLoadedCache = new Map(); - #end + @:noCompletion private var bytesLoadedCache = new Map<#if !disable_preloader_assets AssetLibrary #else Dynamic #end, Int>(); @:noCompletion private var bytesLoadedCache2 = new Map(); @:noCompletion private var bytesTotal:Int; @:noCompletion private var bytesTotalCache = new Map(); @:noCompletion private var initLibraryNames:Bool; - #if !disable_preloader_assets - @:noCompletion private var libraries:Array; + @:noCompletion private var libraries:Array<#if !disable_preloader_assets AssetLibrary #else Dynamic #end>; @:noCompletion private var libraryNames:Array; @:noCompletion private var loadedLibraries:Int; - #end @:noCompletion private var loadedStage:Bool; @:noCompletion private var preloadComplete:Bool; @:noCompletion private var preloadStarted:Bool; @@ -63,10 +59,8 @@ class Preloader #if flash extends Sprite #end bytesLoaded = 0; bytesTotal = 0; - #if !disable_preloader_assets - libraries = new Array(); + libraries = new Array<#if !disable_preloader_assets AssetLibrary #else Dynamic #end>(); libraryNames = new Array(); - #end onProgress.add(update); @@ -111,8 +105,7 @@ class Preloader #if flash extends Sprite #end #end } - #if !disable_preloader_assets - public function addLibrary(library:AssetLibrary):Void + public function addLibrary(library:#if !disable_preloader_assets AssetLibrary #else Dynamic #end):Void { libraries.push(library); } @@ -124,21 +117,17 @@ class Preloader #if flash extends Sprite #end libraryNames.push(name); } } - #end public function load():Void { - #if !disable_preloader_assets for (library in libraries) { bytesTotal += library.bytesTotal; } loadedLibraries = -1; - #end preloadStarted = false; - #if !disable_preloader_assets for (library in libraries) { Log.verbose("Preloading asset library"); @@ -170,7 +159,7 @@ class Preloader #if flash extends Sprite #end } else { - bytesLoaded += library.bytesTotal - bytesLoadedCache.get(library); + bytesLoaded += Std.int(library.bytesTotal) - bytesLoadedCache.get(library); } loadedAssetLibrary(); @@ -189,12 +178,10 @@ class Preloader #if flash extends Sprite #end } loadedLibraries++; - #end preloadStarted = true; updateProgress(); } - #if !disable_preloader_assets @:noCompletion private function loadedAssetLibrary(name:String = null):Void { loadedLibraries++; @@ -215,7 +202,6 @@ class Preloader #if flash extends Sprite #end updateProgress(); } - #end @:noCompletion private function start():Void { @@ -309,8 +295,8 @@ class Preloader #if flash extends Sprite #end } #end - if (!simulateProgress #if flash && loadedStage #end#if !disable_preloader_assets - && loadedLibraries == (libraries.length + libraryNames.length) #end) + if (!simulateProgress #if flash && loadedStage #end + && loadedLibraries == (libraries.length + libraryNames.length)) { if (!preloadComplete) { From da5704e263ead24bb5a50818b0a2ffea1f5ad426 Mon Sep 17 00:00:00 2001 From: Joseph Cloutier Date: Sat, 18 Jun 2022 21:04:32 -0400 Subject: [PATCH 05/29] =?UTF-8?q?Rename=20`ForegroundWorker`=20=E2=86=92?= =?UTF-8?q?=20`JNISafety`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change places the focus on the one known use case, while clearing up potential confusion caused by similar-sounding classes that function totally differently. --- .../main/java/org/haxe/lime/HaxeObject.java | 53 ++++- src/lime/system/ForegroundWorker.hx | 210 ------------------ src/lime/system/JNI.hx | 139 +++++++++++- 3 files changed, 185 insertions(+), 217 deletions(-) delete mode 100644 src/lime/system/ForegroundWorker.hx diff --git a/dependencies/extension-api/src/main/java/org/haxe/lime/HaxeObject.java b/dependencies/extension-api/src/main/java/org/haxe/lime/HaxeObject.java index 2fed7ffb3..88438725d 100644 --- a/dependencies/extension-api/src/main/java/org/haxe/lime/HaxeObject.java +++ b/dependencies/extension-api/src/main/java/org/haxe/lime/HaxeObject.java @@ -11,13 +11,54 @@ import java.lang.Float; import java.lang.Double; /** - An object that was originally created by Haxe code. You can call its - functions using `callX("functionName")`, where X is the number of arguments. + A placeholder for an object created in Haxe. You can call the object's + functions using `callN("functionName")`, where N is the number of arguments. - Caution: the Haxe function will run on the thread you called it from. In many - cases, this will be the UI thread, which is _not_ the same as Haxe's main - thread. To avoid unpredictable thread-related errors, consider using a - `lime.system.ForegroundWorker` as your `HaxeObject`. + Caution: the Haxe function will run on whichever thread you call it from. + Java code typically runs on the UI thread, not Haxe's main thread, which can + easily cause thread-related errors. This cannot be easily remedied using Java + code, but is fixable in Haxe using `lime.system.JNI.JNISafety`. + + Sample usage: + + ```haxe + // MyHaxeObject.hx + import lime.system.JNI; + + class MyHaxeObject implements JNISafety + { + @:runOnMainThread + public function onActivityResult(requestCode:Int, resultCode:Int):Void + { + // Insert code to process the result. This code will safely run on the + // main Haxe thread. + } + } + ``` + + ```java + // MyJavaTool.java + import android.content.Intent; + import org.haxe.extension.Extension; + import org.haxe.lime.HaxeObject; + + public class MyJavaTool extends Extension + { + private static var haxeObject:HaxeObject; + + public static function registerHaxeObject(object:HaxeObject) + { + haxeObject = object; + } + + // onActivityResult() always runs on the Android UI thread. + @Override public boolean onActivityResult(int requestCode, int resultCode, Intent data) + { + haxeObject.call2(requestCode, resultCode); + return true; + } + } + ``` **/ public class HaxeObject { diff --git a/src/lime/system/ForegroundWorker.hx b/src/lime/system/ForegroundWorker.hx deleted file mode 100644 index 984ea2d56..000000000 --- a/src/lime/system/ForegroundWorker.hx +++ /dev/null @@ -1,210 +0,0 @@ -package lime.system; - -import haxe.macro.Context; -import haxe.macro.Expr; -import haxe.macro.Type; -#if target.threaded -import sys.thread.Thread; -#elseif cpp -import cpp.vm.Thread; -#elseif neko -import neko.vm.Thread; -#end - -/** - An object whose instance functions always run on the main thread. If called - from any other thread, they'll switch to the main thread before proceeding. - This is important for Android apps that use JNI, as most times a Java class - calls a Haxe function, it does so on the UI thread. - - Usage: - - ```haxe - class MyClass extends ForegroundWorker - { - public function foregroundFunction():Void - { - // Code here is guaranteed to run on Haxe's main thread. - } - - @:anyThread public function anyThreadFunction():Void - { - // Code here will run on whichever thread calls the function, thanks - // to `@:anyThread`. - } - } - ``` - - @see `ForegroundWorkerBuilder` for details and more options. -**/ -#if (target.threaded || cpp || neko) -@:autoBuild(lime.system.ForegroundWorkerBuilder.modifyInstanceFunctions()) -#end -// Yes, this could also be an interface, but that opens up edge cases. Better to -// leave those for advanced users who use `ForegroundWorkerBuilder`. -class ForegroundWorker -{ - #if (target.threaded || cpp || neko) - private static var mainThread:Thread = Thread.current(); - #end - - /** - @return Whether the calling function is being run on the main thread. - **/ - public static inline function onMainThread():Bool - { - #if (target.threaded || cpp || neko) - return Thread.current() == mainThread; - #else - return true; - #end - } -} - -class ForegroundWorkerBuilder -{ - /** - A build macro that iterates through a class's instance functions - (excluding those marked `@:anyThread`) and inserts code to ensure these - functions run only on the main thread. - - Caution: build macros never directly modify superclasses. To make a - superclass's functions run on the main thread, either annotate that - class with its own `@:build` metadata or override all of its functions. - - Usage: - - ```haxe - @:build(lime.system.ForegroundWorker.ForegroundWorkerBuilder.modifyInstanceFunctions()) - class MyClass - { - public var array0:Array = []; - private var array1:Array = []; - - public function copyItems():Void - { - //Thread safety code will be inserted automatically. You can - //write thread-unsafe code as normal. - for (i in 0...array0.length) - if (this.array0[i] != null) - this.array1.push(this.array0[i]); - } - } - ``` - **/ - public static macro function modifyInstanceFunctions():Array - { - var fields:Array = Context.getBuildFields(); - - for (field in fields) - { - if (field.access.indexOf(AStatic) >= 0) - continue; - - modifyField(field); - } - - return fields; - } - - /** - A build macro that iterates through a class's static functions - (excluding those marked `@:anyThread`) and inserts code to ensure these - functions run only on the main thread. - - Usage: - - ```haxe - @:build(lime.system.ForegroundWorker.ForegroundWorkerBuilder.modifyStaticFunctions()) - class MyClass - { - private static var eventCount:Map = new Map(); - public static function countEvent(event:String):Void - { - //Thread safety code will be inserted automatically. You can - //write thread-unsafe code as normal. - if (eventCount.exists(event)) - eventCount[event]++; - else - eventCount[event] = 1; - } - } - ``` - **/ - public static macro function modifyStaticFunctions():Array - { - var fields:Array = Context.getBuildFields(); - - for (field in fields) - { - if (field.access.indexOf(AStatic) < 0) - continue; - - modifyField(field); - } - - return fields; - } - - #if macro - private static function modifyField(field:Field):Void - { - if (field.name == "new") - return; - - if (field.meta != null) - { - for (meta in field.meta) - { - if (meta.name == ":anyThread") - return; - } - } - - switch (field.kind) - { - case FFun(f): - field.access.remove(AInline); - - var qualifiedIdent:Array; - if (field.access.indexOf(AStatic) >= 0) - { - if (Context.getLocalClass() == null) - throw "ForegroundWorkerBuilder is only designed to work on classes."; - - var localClass:ClassType = Context.getLocalClass().get(); - qualifiedIdent = localClass.pack.copy(); - if (localClass.module != localClass.name) - qualifiedIdent.push(localClass.module); - qualifiedIdent.push(localClass.name); - } - else - { - qualifiedIdent = []; - } - qualifiedIdent.push(field.name); - - var args:Array = [for (arg in f.args) macro $i{arg.name}]; - - var exprs:Array; - switch (f.expr.expr) - { - case EBlock(e): - exprs = e; - default: - exprs = [f.expr]; - f.expr = { pos: field.pos, expr: EBlock(exprs) }; - } - - exprs.unshift(macro - if (!lime.system.ForegroundWorker.onMainThread()) - { - haxe.MainLoop.runInMainThread($p{qualifiedIdent}.bind($a{args})); - return; - } - ); - default: - } - } - #end -} diff --git a/src/lime/system/JNI.hx b/src/lime/system/JNI.hx index 1d240aff3..ad2577f71 100644 --- a/src/lime/system/JNI.hx +++ b/src/lime/system/JNI.hx @@ -1,7 +1,22 @@ package lime.system; #if (!lime_doc_gen || android) +#if macro +import haxe.macro.Context; +import haxe.macro.Expr; +import haxe.macro.Type; +#else import lime._internal.backend.native.NativeCFFI; +#end +#if !lime_doc_gen +#if target.threaded +import sys.thread.Thread; +#elseif cpp +import cpp.vm.Thread; +#elseif neko +import neko.vm.Thread; +#end +#end /** The Java Native Interface (JNI) allows C++ code to call Java functions, and @@ -19,7 +34,7 @@ import lime._internal.backend.native.NativeCFFI; Note that most Java code runs on a different thread than Haxe, meaning that you can get thread-related errors in both directions. Java functions can use `Extension.callbackHandler.post()` to switch to the UI thread, while - Haxe code can avoid the problem using `lime.system.ForegroundWorker`. + Haxe code can avoid the problem using `lime.system.JNI.JNISafety`. **/ #if !lime_debug @:fileXml('tags="haxe,release"') @@ -325,4 +340,126 @@ class JNIMethod } } } + +/** + Most times a Java class calls a Haxe function, it does so on the UI thread, + which can lead to thread-related errors. These errors can be avoided by + switching back to the main thread before executing any code. + + Usage: + + ```haxe + class MyClass implements JNISafety + { + @:runOnMainThread + public function callbackFunction(data:Dynamic):Void + { + // Code here is guaranteed to run on Haxe's main thread. It's safe + // to call `callbackFunction` via JNI. + } + + public function notACallbackFunction():Void + { + // Code here will run on whichever thread calls the function. It may + // not be safe to call `notACallbackFunction` via JNI. + } + } + ``` +**/ +// Haxe 3 can't parse "target.threaded" inside parentheses. +#if !lime_doc_gen +#if target.threaded +@:autoBuild(lime.system.JNI.JNISafetyTools.build()) +#elseif (cpp || neko) +@:autoBuild(lime.system.JNI.JNISafetyTools.build()) +#end +#end +interface JNISafety {} + +#if !lime_doc_gen +class JNISafetyTools +{ + #if target.threaded + private static var mainThread:Thread = Thread.current(); + #elseif (cpp || neko) + private static var mainThread:Thread = Thread.current(); + #end + + /** + @return Whether the calling function is being run on the main thread. + **/ + public static inline function onMainThread():Bool + { + #if target.threaded + return Thread.current() == mainThread; + #elseif (cpp || neko) + return Thread.current() == mainThread; + #else + return true; + #end + } + + public static macro function build():Array + { + var fields:Array = Context.getBuildFields(); + + #if macro + for (field in fields) + { + // Don't modify constructors. + if (field.name == "new") + { + continue; + } + + // Don't modify functions lacking `@:runOnMainThread`. + if (field.meta == null || !Lambda.exists(field.meta, + function(meta) return meta.name == ":runOnMainThread")) + { + continue; + } + + switch (field.kind) + { + case FFun(f): + // The function needs to call itself and can't be inline. + field.access.remove(AInline); + + // Make sure there's no return value. + switch (f.ret) + { + case macro:Void: + // Good to go. + case null: + f.ret = macro:Void; + default: + Context.error("Expected return type Void, got " + + new haxe.macro.Printer().printComplexType(f.ret) + ".", field.pos); + } + + var args:Array = []; + for (arg in f.args) + { + args.push(macro $i{arg.name}); + + // Account for an unlikely edge case. + if (arg.name == field.name) + Context.error('${field.name}() should not take an argument named ${field.name}.', field.pos); + } + + // Check the thread before running the function. + f.expr = macro + if (!lime.system.JNI.JNISafetyTools.onMainThread()) + haxe.MainLoop.runInMainThread($i{field.name}.bind($a{args})) + else + ${f.expr}; + default: + } + } + #end + + return fields; + } +} +#end #end From 0125e939a91483b1a2f3d36a8f46ffb58ceb8bf5 Mon Sep 17 00:00:00 2001 From: mgambrell Date: Mon, 4 Jul 2022 00:00:38 -0500 Subject: [PATCH 06/29] vorbisfile.cpp - change free(x) to `delete x` (fixes #1556) --- project/src/media/codecs/vorbis/VorbisFile.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/project/src/media/codecs/vorbis/VorbisFile.cpp b/project/src/media/codecs/vorbis/VorbisFile.cpp index bb05c613e..ab4a0a441 100644 --- a/project/src/media/codecs/vorbis/VorbisFile.cpp +++ b/project/src/media/codecs/vorbis/VorbisFile.cpp @@ -81,7 +81,7 @@ namespace lime { static int VorbisFile_BufferClose (VorbisFile_Buffer* src) { - free (src); + delete src; return 0; } @@ -154,8 +154,8 @@ namespace lime { if (ov_open_callbacks (buffer, vorbisFile, NULL, 0, VORBIS_FILE_BUFFER_CALLBACKS) != 0) { - free (buffer); - free (vorbisFile); + delete buffer; + delete vorbisFile; return 0; } @@ -178,7 +178,7 @@ namespace lime { if (ov_open_callbacks (file, vorbisFile, NULL, 0, VORBIS_FILE_FILE_CALLBACKS) != 0) { - free (vorbisFile); + delete vorbisFile; lime::fclose (file); return 0; From 7e33d526453b27f8542c752b6567bc9ac86b2834 Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Tue, 5 Jul 2022 08:49:08 -0700 Subject: [PATCH 07/29] docs: logo not required to be served from root of domain --- assets/docs-theme/resources/extra-styles.css | 6 ++++++ docs/build.hx | 3 --- docs/build.hxml | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 assets/docs-theme/resources/extra-styles.css diff --git a/assets/docs-theme/resources/extra-styles.css b/assets/docs-theme/resources/extra-styles.css new file mode 100644 index 000000000..3acff1686 --- /dev/null +++ b/assets/docs-theme/resources/extra-styles.css @@ -0,0 +1,6 @@ +body .navbar .brand:first-of-type { + background: url(./images/logo.png) center left no-repeat; + background-size: 32px 32px; + padding-left: 40px; + margin: 0.5em 0; +} \ No newline at end of file diff --git a/docs/build.hx b/docs/build.hx index 35fdc1e8a..97538d6c2 100644 --- a/docs/build.hx +++ b/docs/build.hx @@ -72,9 +72,6 @@ class Build extends Script "website", "http://lime.software", "-D", - "logo", - "/images/logo.png", - "-D", "textColor", "0x777777", "-theme", diff --git a/docs/build.hxml b/docs/build.hxml index cf804abe9..544599928 100644 --- a/docs/build.hxml +++ b/docs/build.hxml @@ -13,4 +13,4 @@ hxml/android.hxml hxml/html5.hxml --next --cmd haxelib run dox -i xml -in lime --title "Lime API Reference" -D website "http://lime.software" -D source-path "https://github.com/openfl/lime/tree/develop/src/" -D logo "/images/logo.png" -D textColor 0x777777 -theme ../assets/docs-theme --toplevel-package lime \ No newline at end of file +-cmd haxelib run dox -i xml -in lime --title "Lime API Reference" -D website "http://lime.software" -D source-path "https://github.com/openfl/lime/tree/develop/src/" -D textColor 0x777777 -theme ../assets/docs-theme --toplevel-package lime \ No newline at end of file From 8d715cb741d7945137fc691aa5509f8162a37e7f Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Tue, 5 Jul 2022 08:51:01 -0700 Subject: [PATCH 08/29] docs website URL This may change, but this is where it is right now --- docs/build.hx | 2 +- docs/build.hxml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/build.hx b/docs/build.hx index 97538d6c2..2caf32fc7 100644 --- a/docs/build.hx +++ b/docs/build.hx @@ -70,7 +70,7 @@ class Build extends Script "https://github.com/openfl/lime/tree/develop/src/", "-D", "website", - "http://lime.software", + "http://openfl.github.io/lime.software", "-D", "textColor", "0x777777", diff --git a/docs/build.hxml b/docs/build.hxml index 544599928..da1273662 100644 --- a/docs/build.hxml +++ b/docs/build.hxml @@ -13,4 +13,4 @@ hxml/android.hxml hxml/html5.hxml --next --cmd haxelib run dox -i xml -in lime --title "Lime API Reference" -D website "http://lime.software" -D source-path "https://github.com/openfl/lime/tree/develop/src/" -D textColor 0x777777 -theme ../assets/docs-theme --toplevel-package lime \ No newline at end of file +-cmd haxelib run dox -i xml -in lime --title "Lime API Reference" -D website "http://openfl.github.io/lime.software" -D source-path "https://github.com/openfl/lime/tree/develop/src/" -D textColor 0x777777 -theme ../assets/docs-theme --toplevel-package lime \ No newline at end of file From f004b968d0fa2f592e47c3407088572db76535dc Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Mon, 11 Jul 2022 14:53:34 -0700 Subject: [PATCH 09/29] README: link to development builds shows only successful builds --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ee89b399..3b08328bf 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ First install the latest version of [Haxe](http://www.haxe.org/download). Development Builds ================== -When there are changes, Lime is built nightly. Builds are available for download [here](https://github.com/openfl/lime/actions?query=branch%3Adevelop). +When there are changes, Lime is built nightly. Builds are available for download [here](https://github.com/openfl/lime/actions?query=branch%3Adevelop+is%3Asuccess). To install a development build, use the "haxelib local" command: From 06baca43962846e32cc2d4c7c73a730c2639dacd Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Mon, 11 Jul 2022 15:29:28 -0700 Subject: [PATCH 10/29] README: use correct file name for installing nightly build --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b08328bf..8ec70953a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ When there are changes, Lime is built nightly. Builds are available for download To install a development build, use the "haxelib local" command: - haxelib local filename.zip + haxelib local lime-haxelib.zip Building from Source From fd0fc3da48335bd60e15696aeb7781e6d9d22703 Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Wed, 13 Jul 2022 10:01:06 -0700 Subject: [PATCH 11/29] HashLink: fix the ability to double-click the .app file on macOS to run it The HashLink executable expects hlboot.dat and libraries to be in the current working directory (it's not enough for them to be in the same directory as the executable). Make the .app file launch a shell script that 1) changes the current working directory 2) launches the HashLink executable --- templates/hl/mac-launch.sh | 4 ++++ tools/platforms/MacPlatform.hx | 14 ++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 templates/hl/mac-launch.sh diff --git a/templates/hl/mac-launch.sh b/templates/hl/mac-launch.sh new file mode 100644 index 000000000..7f3b77fca --- /dev/null +++ b/templates/hl/mac-launch.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +# HashLink needs a specific working directory to find hlboot.dat and libraries +cd "$(dirname "$0")" +exec ./hl \ No newline at end of file diff --git a/tools/platforms/MacPlatform.hx b/tools/platforms/MacPlatform.hx index 8829ac3ad..4f80be65a 100644 --- a/tools/platforms/MacPlatform.hx +++ b/tools/platforms/MacPlatform.hx @@ -207,6 +207,20 @@ class MacPlatform extends PlatformTarget if (noOutput) return; HashlinkHelper.copyHashlink(project, targetDirectory, executableDirectory, executablePath, is64); + + // HashLink looks for hlboot.dat and libraries in the current + // working directory, so the .app file won't work properly if it + // tries to run the HashLink executable directly. + // when the .app file is launched, we can tell it to run a shell + // script instead of the HashLink executable. the shell script will + // adjusts the working directory before running the HL executable. + + // unlike other platforms, we want to use the original "hl" name + var hlExecutablePath = Path.combine(executableDirectory, "hl"); + System.renameFile(executablePath, hlExecutablePath); + System.runCommand("", "chmod", ["755", hlExecutablePath]); + // then we can use the executable name for the shell script + System.copyFileTemplate(project.templatePaths, 'hl/mac-launch.sh', executablePath); } else if (targetType == "java") { From 795b2fcace6f47905a1a81e90402889a93d8591c Mon Sep 17 00:00:00 2001 From: Josh Tynjala Date: Mon, 18 Jul 2022 09:54:51 -0700 Subject: [PATCH 12/29] docs-theme: dark mode support --- assets/docs-theme/resources/index.js | 18 +++++++++++++++++- assets/docs-theme/templates/topbar.mtt | 6 ++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/assets/docs-theme/resources/index.js b/assets/docs-theme/resources/index.js index 65ce23954..65b08cc6e 100644 --- a/assets/docs-theme/resources/index.js +++ b/assets/docs-theme/resources/index.js @@ -6,6 +6,22 @@ function readCookie(name) { return localStorage.getItem(name); } +function isDarkTheme() { + return document.querySelector("html").classList.contains("dark-theme"); +} + +function toggleTheme() { + const htmlTag = document.querySelector("html"); + let isDark = isDarkTheme(); + if (isDark) { + htmlTag.classList.remove("dark-theme"); + } else { + htmlTag.classList.add("dark-theme"); + } + isDark = isDarkTheme(); + localStorage.theme = isDark ? "dark" : "light"; +} + function toggleInherited(el) { var toggle = $(el).closest(".toggle"); toggle.toggleClass("toggle-on"); @@ -131,7 +147,7 @@ $(document).ready(function(){ } return true; }); - + $("#select-platform").selectpicker().on("change", function(e){ var value = $(":selected", this).val(); setPlatform(value); diff --git a/assets/docs-theme/templates/topbar.mtt b/assets/docs-theme/templates/topbar.mtt index e23d53522..89ae802bd 100644 --- a/assets/docs-theme/templates/topbar.mtt +++ b/assets/docs-theme/templates/topbar.mtt @@ -1,6 +1,6 @@