mirror of
https://github.com/geode-sdk/android-launcher.git
synced 2026-10-21 16:32:39 +00:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df513983d1 | ||
|
|
a71071e3ac | ||
|
|
8578200db1 | ||
|
|
adb9dcc1e9 | ||
|
|
a32589b06c | ||
|
|
1773e54c84 | ||
|
|
5718b73470 |
No files matched your search
+12
-9
@@ -1,4 +1,5 @@
|
|||||||
import groovy.json.JsonSlurper
|
import groovy.json.JsonSlurper
|
||||||
|
import java.io.IOException
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
@@ -15,7 +16,7 @@ plugins {
|
|||||||
id("org.jetbrains.kotlin.plugin.compose")
|
id("org.jetbrains.kotlin.plugin.compose")
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentGeodeVersion = "5.11.2"
|
val currentGeodeVersion = "5.10.1"
|
||||||
|
|
||||||
abstract class DownloadVersionMetadataTask : DefaultTask() {
|
abstract class DownloadVersionMetadataTask : DefaultTask() {
|
||||||
@get:Input
|
@get:Input
|
||||||
@@ -247,9 +248,9 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.geode.launcher"
|
applicationId = "com.geode.launcher"
|
||||||
minSdk = 23
|
minSdk = 23
|
||||||
targetSdk = 37
|
targetSdk = 36
|
||||||
versionCode = 31
|
versionCode = 30
|
||||||
versionName = "1.9.0"
|
versionName = "1.8.0"
|
||||||
|
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary = true
|
useSupportLibrary = true
|
||||||
@@ -317,6 +318,7 @@ android {
|
|||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
|
prefab = true
|
||||||
}
|
}
|
||||||
packaging {
|
packaging {
|
||||||
resources {
|
resources {
|
||||||
@@ -330,7 +332,7 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
namespace = "com.geode.launcher"
|
namespace = "com.geode.launcher"
|
||||||
ndkVersion = "30.0.16248370"
|
ndkVersion = "29.0.14206865"
|
||||||
}
|
}
|
||||||
|
|
||||||
androidComponents {
|
androidComponents {
|
||||||
@@ -347,8 +349,8 @@ androidComponents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation (platform("androidx.compose:compose-bom:2026.09.00"))
|
implementation (platform("androidx.compose:compose-bom:2026.08.00"))
|
||||||
implementation ("androidx.core:core-ktx:1.19.1")
|
implementation ("androidx.core:core-ktx:1.19.0")
|
||||||
implementation ("androidx.compose.ui:ui")
|
implementation ("androidx.compose.ui:ui")
|
||||||
implementation ("androidx.compose.material3:material3")
|
implementation ("androidx.compose.material3:material3")
|
||||||
implementation ("androidx.compose.ui:ui-tooling-preview")
|
implementation ("androidx.compose.ui:ui-tooling-preview")
|
||||||
@@ -358,6 +360,7 @@ dependencies {
|
|||||||
implementation ("androidx.activity:activity-ktx:1.13.0")
|
implementation ("androidx.activity:activity-ktx:1.13.0")
|
||||||
implementation ("androidx.appcompat:appcompat:1.8.0")
|
implementation ("androidx.appcompat:appcompat:1.8.0")
|
||||||
implementation ("androidx.documentfile:documentfile:1.1.0")
|
implementation ("androidx.documentfile:documentfile:1.1.0")
|
||||||
|
implementation ("androidx.games:games-frame-pacing:2.1.3")
|
||||||
|
|
||||||
implementation ("com.squareup.okio:okio:3.18.2")
|
implementation ("com.squareup.okio:okio:3.18.2")
|
||||||
implementation ("com.squareup.okhttp3:okhttp:5.5.0")
|
implementation ("com.squareup.okhttp3:okhttp:5.5.0")
|
||||||
@@ -367,8 +370,8 @@ dependencies {
|
|||||||
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.11.0")
|
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.11.0")
|
||||||
implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
|
implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
|
||||||
|
|
||||||
implementation ("com.mikepenz:multiplatform-markdown-renderer-android:0.46.0")
|
implementation ("com.mikepenz:multiplatform-markdown-renderer-android:0.45.0")
|
||||||
implementation ("com.mikepenz:multiplatform-markdown-renderer-m3:0.46.0")
|
implementation ("com.mikepenz:multiplatform-markdown-renderer-m3:0.45.0")
|
||||||
implementation ("androidx.browser:browser:1.10.0")
|
implementation ("androidx.browser:browser:1.10.0")
|
||||||
debugImplementation ("androidx.compose.ui:ui-tooling")
|
debugImplementation ("androidx.compose.ui:ui-tooling")
|
||||||
coreLibraryDesugaring ("com.android.tools:desugar_jdk_libs:2.1.5")
|
coreLibraryDesugaring ("com.android.tools:desugar_jdk_libs:2.1.5")
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".GeometryDashActivity"
|
android:name=".GeometryDashActivity"
|
||||||
android:configChanges="fontScale|layoutDirection|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|locale"
|
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:screenOrientation="landscape"
|
android:screenOrientation="landscape"
|
||||||
@@ -233,26 +233,6 @@
|
|||||||
<data android:scheme="geode-launcher" android:host="main" />
|
<data android:scheme="geode-launcher" android:host="main" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
<activity-alias
|
|
||||||
android:name=".MainActivityGreen"
|
|
||||||
android:enabled="false"
|
|
||||||
android:exported="true"
|
|
||||||
android:icon="@mipmap/ic_launcher_green"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:targetActivity=".MainActivity">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
|
||||||
<data android:scheme="geode-launcher" android:host="main" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity-alias>
|
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".UserDirectoryProvider"
|
android:name=".UserDirectoryProvider"
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ cmake_minimum_required(VERSION 3.21)
|
|||||||
|
|
||||||
project(launcherfix)
|
project(launcherfix)
|
||||||
|
|
||||||
add_library(launcherfix SHARED launcher-fix.cpp patcher.cpp)
|
find_package(games-frame-pacing REQUIRED CONFIG)
|
||||||
|
|
||||||
|
add_library(launcherfix SHARED launcher-fix.cpp patcher.cpp pacing.cpp)
|
||||||
|
|
||||||
target_compile_features(launcherfix PUBLIC cxx_std_20)
|
target_compile_features(launcherfix PUBLIC cxx_std_20)
|
||||||
set_target_properties(launcherfix PROPERTIES CXX_EXTENSIONS OFF)
|
set_target_properties(launcherfix PROPERTIES CXX_EXTENSIONS OFF)
|
||||||
@@ -14,4 +16,5 @@ set_target_properties(launcherfix PROPERTIES
|
|||||||
CXX_VISIBILITY_PRESET hidden
|
CXX_VISIBILITY_PRESET hidden
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(launcherfix PRIVATE log)
|
target_link_libraries(launcherfix PRIVATE log android)
|
||||||
|
target_link_libraries(launcherfix PRIVATE games-frame-pacing::swappy_static)
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#include <swappy/swappyGL.h>
|
||||||
|
#include <swappy/swappyGL_extra.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT void JNICALL Java_com_geode_launcher_LauncherFix_initFramePacing(
|
||||||
|
JNIEnv *env,
|
||||||
|
jobject,
|
||||||
|
jobject activity
|
||||||
|
) {
|
||||||
|
SwappyGL_init(env, activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NativeWindowDeleter {
|
||||||
|
void operator()(ANativeWindow* p) const {
|
||||||
|
if (p != nullptr) ANativeWindow_release(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<ANativeWindow, NativeWindowDeleter> native_window = nullptr;
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT void JNICALL Java_com_geode_launcher_LauncherFix_destroyFramePacing(JNIEnv*, jobject) {
|
||||||
|
SwappyGL_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jboolean JNICALL Java_com_geode_launcher_LauncherFix_swapFrame(
|
||||||
|
JNIEnv*,
|
||||||
|
jobject,
|
||||||
|
jlong display,
|
||||||
|
jlong surface
|
||||||
|
) {
|
||||||
|
return SwappyGL_swap(
|
||||||
|
reinterpret_cast<EGLDisplay>(display),
|
||||||
|
reinterpret_cast<EGLSurface>(surface)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT void JNICALL Java_com_geode_launcher_LauncherFix_setSurface(
|
||||||
|
JNIEnv* env,
|
||||||
|
jobject,
|
||||||
|
jobject surface
|
||||||
|
) {
|
||||||
|
if (surface == nullptr) {
|
||||||
|
native_window.reset();
|
||||||
|
SwappyGL_setWindow(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
native_window.reset(ANativeWindow_fromSurface(env, surface));
|
||||||
|
SwappyGL_setWindow(native_window.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT void JNICALL Java_com_geode_launcher_LauncherFix_setSwapInterval(
|
||||||
|
JNIEnv* env,
|
||||||
|
jobject,
|
||||||
|
jlong interval_ns
|
||||||
|
) {
|
||||||
|
SwappyGL_setAutoSwapInterval(false);
|
||||||
|
SwappyGL_setSwapIntervalNS(interval_ns);
|
||||||
|
}
|
||||||
@@ -2,106 +2,33 @@ package com.customRobTop
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.*
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.DocumentsContract
|
|
||||||
import android.provider.OpenableColumns
|
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.customRobTop.contracts.ImportFileActivityContract
|
|
||||||
import com.customRobTop.contracts.ShareFileActivityContract
|
|
||||||
import com.geode.launcher.R
|
import com.geode.launcher.R
|
||||||
import com.geode.launcher.utils.DownloadUtils
|
|
||||||
import com.geode.launcher.utils.LaunchUtils
|
|
||||||
import org.cocos2dx.lib.Cocos2dxGLSurfaceView
|
|
||||||
import org.cocos2dx.lib.Cocos2dxGLSurfaceView.Companion.closeIMEKeyboard
|
import org.cocos2dx.lib.Cocos2dxGLSurfaceView.Companion.closeIMEKeyboard
|
||||||
import org.cocos2dx.lib.Cocos2dxGLSurfaceView.Companion.openIMEKeyboard
|
import org.cocos2dx.lib.Cocos2dxGLSurfaceView.Companion.openIMEKeyboard
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.OutputStream
|
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.UUID
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@Suppress("unused", "UNUSED_PARAMETER")
|
@Suppress("unused", "UNUSED_PARAMETER")
|
||||||
object BaseRobTopActivity {
|
object BaseRobTopActivity {
|
||||||
const val KEYBOARD_INPUT_MULTILINE = 1
|
|
||||||
const val KEYBOARD_INPUT_NUMERIC = 4
|
|
||||||
const val KEYBOARD_INPUT_PASSWORD = 2
|
|
||||||
const val LEVEL_EXTENSION: String = ".gdlvl"
|
|
||||||
|
|
||||||
private var isLoaded = false
|
private var isLoaded = false
|
||||||
var blockBackButton = false
|
var blockBackButton = false
|
||||||
private var keyboardActive = false
|
private var keyboardActive = false
|
||||||
var curKeyboardInputFlags = 0
|
|
||||||
|
|
||||||
var isPaused = false
|
var isPaused = false
|
||||||
|
|
||||||
lateinit var me: WeakReference<Activity>
|
lateinit var me: WeakReference<Activity>
|
||||||
private var shouldResumeSound = true
|
private var shouldResumeSound = true
|
||||||
|
|
||||||
private var pendingExportPaths = emptyList<String>()
|
fun setCurrentActivity(currentActivity: Activity) {
|
||||||
|
|
||||||
private lateinit var importFileActivityContract: ActivityResultLauncher<Unit>
|
|
||||||
private lateinit var shareFileActivityContract: ActivityResultLauncher<String>
|
|
||||||
private lateinit var shareFolderActivityContract: ActivityResultLauncher<Uri?>
|
|
||||||
|
|
||||||
fun setCurrentActivity(currentActivity: AppCompatActivity) {
|
|
||||||
me = WeakReference(currentActivity)
|
me = WeakReference(currentActivity)
|
||||||
|
|
||||||
importFileActivityContract = currentActivity.registerForActivityResult(ImportFileActivityContract()) { uris ->
|
|
||||||
val filePaths = copyPickedFiles(uris)
|
|
||||||
|
|
||||||
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
JniToCpp.filesPicked(filePaths.toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shareFileActivityContract = currentActivity.registerForActivityResult(ShareFileActivityContract()) { uri ->
|
|
||||||
val currentlyPending = pendingExportPaths
|
|
||||||
pendingExportPaths = emptyList()
|
|
||||||
|
|
||||||
val exportPath = currentlyPending.firstOrNull()
|
|
||||||
if (exportPath == null || uri == null) {
|
|
||||||
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
JniToCpp.fileShareFinished(false)
|
|
||||||
}
|
|
||||||
return@registerForActivityResult
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = saveToDocument(exportPath, uri)
|
|
||||||
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
JniToCpp.fileShareFinished(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shareFolderActivityContract = currentActivity.registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
|
|
||||||
val currentlyPending = pendingExportPaths
|
|
||||||
pendingExportPaths = emptyList()
|
|
||||||
|
|
||||||
if (uri == null) {
|
|
||||||
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
JniToCpp.fileShareFinished(false)
|
|
||||||
}
|
|
||||||
return@registerForActivityResult
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = saveToFolder(currentlyPending, uri) > 0
|
|
||||||
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
JniToCpp.fileShareFinished(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("HardwareIds")
|
@SuppressLint("HardwareIds")
|
||||||
@@ -160,18 +87,6 @@ object BaseRobTopActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun getClipboardString(): String {
|
|
||||||
me.get()?.run {
|
|
||||||
val manager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
val clip = manager.primaryClip
|
|
||||||
if (clip != null && clip.itemCount > 0) {
|
|
||||||
return clip.getItemAt(0).coerceToText(this).toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun sendMail(subject: String, body: String, to: String) {
|
fun sendMail(subject: String, body: String, to: String) {
|
||||||
me.get()?.runOnUiThread {
|
me.get()?.runOnUiThread {
|
||||||
@@ -349,164 +264,4 @@ object BaseRobTopActivity {
|
|||||||
level = DeprecationLevel.HIDDEN
|
level = DeprecationLevel.HIDDEN
|
||||||
)
|
)
|
||||||
fun logEvent(event: String) {}
|
fun logEvent(event: String) {}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun setKeyboardInputFlags(flags: Int) {
|
|
||||||
curKeyboardInputFlags = flags
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun pickImportFiles() {
|
|
||||||
try {
|
|
||||||
importFileActivityContract.launch(Unit)
|
|
||||||
} catch (_: ActivityNotFoundException) {
|
|
||||||
me.get()?.apply {
|
|
||||||
runOnUiThread {
|
|
||||||
Toast.makeText(
|
|
||||||
this,
|
|
||||||
R.string.no_activity_found,
|
|
||||||
Toast.LENGTH_SHORT,
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun copyPickedFiles(uris: List<Uri>): List<String> {
|
|
||||||
val me = me.get() ?: return emptyList()
|
|
||||||
|
|
||||||
val importsDir = File(LaunchUtils.getSaveDirectory(me), "imports")
|
|
||||||
importsDir.mkdirs()
|
|
||||||
|
|
||||||
return uris.mapIndexedNotNull { index, uri ->
|
|
||||||
val displayName = displayName(uri)
|
|
||||||
?: "import_$index$LEVEL_EXTENSION"
|
|
||||||
if (!displayName.endsWith(LEVEL_EXTENSION)) {
|
|
||||||
return@mapIndexedNotNull null
|
|
||||||
}
|
|
||||||
|
|
||||||
var outputFile = File(importsDir, displayName)
|
|
||||||
var counter = 2
|
|
||||||
while (outputFile.exists()) {
|
|
||||||
outputFile = File(importsDir, "${counter}_$displayName")
|
|
||||||
counter++
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
me.contentResolver.openInputStream(uri)?.use { input ->
|
|
||||||
outputFile.outputStream().use { output ->
|
|
||||||
DownloadUtils.copyFile(input, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
outputFile.absolutePath
|
|
||||||
}
|
|
||||||
} catch (_: Exception) {
|
|
||||||
outputFile.delete()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun displayName(uri: Uri): String? {
|
|
||||||
me.get()?.contentResolver?.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null)?.use { cursorQuery ->
|
|
||||||
if (cursorQuery.moveToFirst()) {
|
|
||||||
val displayName = cursorQuery.getString(0)
|
|
||||||
if (displayName.isNotEmpty()) {
|
|
||||||
return File(displayName).name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun shareFiles(files: Array<String>) {
|
|
||||||
pendingExportPaths = files.toList()
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (files.size == 1) {
|
|
||||||
shareFileActivityContract.launch(files.first())
|
|
||||||
return
|
|
||||||
} else if (files.size > 1) {
|
|
||||||
shareFolderActivityContract.launch(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} catch (_: ActivityNotFoundException) {
|
|
||||||
me.get()?.apply {
|
|
||||||
runOnUiThread {
|
|
||||||
Toast.makeText(
|
|
||||||
this,
|
|
||||||
R.string.no_activity_found,
|
|
||||||
Toast.LENGTH_SHORT,
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
JniToCpp.fileShareFinished(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveToFolder(exportPaths: List<String>, treeUri: Uri): Int {
|
|
||||||
val uri = DocumentsContract.buildDocumentUriUsingTree(treeUri, DocumentsContract.getTreeDocumentId(treeUri))
|
|
||||||
|
|
||||||
val me = me.get() ?: return 0
|
|
||||||
|
|
||||||
return exportPaths.count { path ->
|
|
||||||
val filename = File(path).name
|
|
||||||
val documentUri = DocumentsContract.createDocument(me.contentResolver, uri, "application/octet-stream", filename)
|
|
||||||
?: return@count false
|
|
||||||
|
|
||||||
saveToDocument(path, documentUri)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveToDocument(exportPath: String, uri: Uri): Boolean {
|
|
||||||
try {
|
|
||||||
FileInputStream(exportPath).use { inputStream ->
|
|
||||||
openOutput(uri).use { outputStream ->
|
|
||||||
if (outputStream != null) {
|
|
||||||
DownloadUtils.copyFile(inputStream, outputStream)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureLevelExtension(uri)
|
|
||||||
return true
|
|
||||||
} catch (_: IOException) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openOutput(uri: Uri): OutputStream? {
|
|
||||||
val me = me.get() ?: return null
|
|
||||||
return try {
|
|
||||||
me.contentResolver.openOutputStream(uri, "wt")
|
|
||||||
} catch (_: IOException) {
|
|
||||||
me.contentResolver.openOutputStream(uri)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ensureLevelExtension(uri: Uri) {
|
|
||||||
val displayName = displayName(uri)
|
|
||||||
if (displayName == null || displayName.endsWith(LEVEL_EXTENSION)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val me = me.get() ?: return
|
|
||||||
|
|
||||||
val extensionIdx = displayName.lastIndexOf(".gdlvl.")
|
|
||||||
val substring = if (extensionIdx < 0) {
|
|
||||||
displayName + LEVEL_EXTENSION
|
|
||||||
} else {
|
|
||||||
displayName.substring(0, extensionIdx + 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
DocumentsContract.renameDocument(me.contentResolver, uri, substring)
|
|
||||||
} catch (_: IOException) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -55,16 +55,4 @@ object JniToCpp {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun videoAdShowed()
|
external fun videoAdShowed()
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
external fun filesPicked(files: Array<String>)
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
external fun fileShareFinished(success: Boolean)
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
external fun textInputCaretToEnd()
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
external fun textInputDone()
|
|
||||||
}
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.customRobTop.contracts
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import androidx.activity.result.contract.ActivityResultContract
|
|
||||||
|
|
||||||
class ImportFileActivityContract : ActivityResultContract<Unit, List<Uri>>() {
|
|
||||||
override fun createIntent(
|
|
||||||
context: Context,
|
|
||||||
input: Unit
|
|
||||||
): Intent {
|
|
||||||
return Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
|
||||||
addCategory(Intent.CATEGORY_OPENABLE)
|
|
||||||
type = "*/*"
|
|
||||||
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun parseResult(
|
|
||||||
resultCode: Int,
|
|
||||||
intent: Intent?
|
|
||||||
): List<Uri> {
|
|
||||||
if (resultCode != Activity.RESULT_OK || intent == null) {
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
val clipData = intent.clipData
|
|
||||||
return if (clipData != null) {
|
|
||||||
List(clipData.itemCount) { i -> clipData.getItemAt(i).uri }
|
|
||||||
} else {
|
|
||||||
val intentData = intent.data
|
|
||||||
if (intentData != null)
|
|
||||||
listOf(intentData)
|
|
||||||
else
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.customRobTop.contracts
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.provider.DocumentsContract
|
|
||||||
import androidx.activity.result.contract.ActivityResultContract
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class ShareFileActivityContract : ActivityResultContract<String, Uri?>() {
|
|
||||||
override fun createIntent(
|
|
||||||
context: Context,
|
|
||||||
input: String
|
|
||||||
): Intent {
|
|
||||||
return Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
|
||||||
addCategory(Intent.CATEGORY_OPENABLE)
|
|
||||||
type = "application/octet-stream"
|
|
||||||
putExtra(Intent.EXTRA_TITLE, File(input).name)
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
putExtra(DocumentsContract.EXTRA_INITIAL_URI,
|
|
||||||
DocumentsContract.buildDocumentUri("com.android.externalstorage.documents", "primary:Download")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun parseResult(
|
|
||||||
resultCode: Int,
|
|
||||||
intent: Intent?
|
|
||||||
): Uri? {
|
|
||||||
if (resultCode != Activity.RESULT_OK || intent == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return intent.data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -5,7 +5,9 @@ import android.content.Intent
|
|||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.opengl.GLSurfaceView
|
import android.opengl.EGL14
|
||||||
|
import android.opengl.EGLConfig
|
||||||
|
import android.opengl.EGLDisplay
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
@@ -43,9 +45,6 @@ import java.io.File
|
|||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import javax.microedition.khronos.egl.EGL10
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig
|
|
||||||
import javax.microedition.khronos.egl.EGLDisplay
|
|
||||||
|
|
||||||
enum class DisplayMode {
|
enum class DisplayMode {
|
||||||
DEFAULT, LIMITED, FULLSCREEN;
|
DEFAULT, LIMITED, FULLSCREEN;
|
||||||
@@ -78,6 +77,7 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
private var mAspectRatio = 0.0f
|
private var mAspectRatio = 0.0f
|
||||||
private var mScreenZoom = 1.0f
|
private var mScreenZoom = 1.0f
|
||||||
private var mScreenZoomFit = false
|
private var mScreenZoomFit = false
|
||||||
|
private var mNativeFramePacing = false
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
setupUIState()
|
setupUIState()
|
||||||
@@ -131,6 +131,10 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
mGLSurfaceView?.manualBackEvents = true
|
mGLSurfaceView?.manualBackEvents = true
|
||||||
|
|
||||||
|
if (mNativeFramePacing) {
|
||||||
|
LauncherFix.initFramePacing(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createVersionFile() {
|
private fun createVersionFile() {
|
||||||
@@ -171,8 +175,7 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
tryLoadLibrary(gdPackageInfo, Constants.FMOD_LIB_NAME)
|
tryLoadLibrary(gdPackageInfo, Constants.FMOD_LIB_NAME)
|
||||||
tryLoadLibrary(gdPackageInfo, Constants.COCOS_LIB_NAME)
|
tryLoadLibrary(gdPackageInfo, Constants.COCOS_LIB_NAME)
|
||||||
|
|
||||||
val gameVersionCode = GamePackageUtils.getGameVersionCode(packageManager)
|
if (GamePackageUtils.getGameVersionCode(packageManager) >= 39L) {
|
||||||
if (gameVersionCode >= 39L) {
|
|
||||||
// this fix requires geode v3, which is 2.206+
|
// this fix requires geode v3, which is 2.206+
|
||||||
// there is a short period in which 2.206 users will still have geode v2, but whatever. ig
|
// there is a short period in which 2.206 users will still have geode v2, but whatever. ig
|
||||||
LauncherFix.enableExceptionsRenaming()
|
LauncherFix.enableExceptionsRenaming()
|
||||||
@@ -183,9 +186,6 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
loadInternalMods()
|
loadInternalMods()
|
||||||
|
|
||||||
val baseView = createView()
|
val baseView = createView()
|
||||||
if (gameVersionCode >= 42L) {
|
|
||||||
mGLSurfaceView?.sendNewCocosEvents = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GeodeUtils.handleSafeArea && Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) {
|
if (!GeodeUtils.handleSafeArea && Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) {
|
||||||
val frameLayoutParams = ViewGroup.LayoutParams(
|
val frameLayoutParams = ViewGroup.LayoutParams(
|
||||||
@@ -209,22 +209,12 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
left = 0, top = 0, right = 0, bottom = 0
|
left = 0, top = 0, right = 0, bottom = 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Cocos2dxGLSurfaceView.onKeyboardInsets(insets)
|
|
||||||
|
|
||||||
WindowInsets.CONSUMED
|
WindowInsets.CONSUMED
|
||||||
}
|
}
|
||||||
|
|
||||||
frameLayout.addView(baseView)
|
frameLayout.addView(baseView)
|
||||||
setContentView(frameLayout)
|
setContentView(frameLayout)
|
||||||
} else {
|
} else {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
||||||
baseView.setOnApplyWindowInsetsListener { view, insets ->
|
|
||||||
Cocos2dxGLSurfaceView.onKeyboardInsets(insets)
|
|
||||||
return@setOnApplyWindowInsetsListener view.onApplyWindowInsets(insets)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setContentView(baseView)
|
setContentView(baseView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,16 +495,14 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
|
|
||||||
val frameRate = mLimitedRefreshRate
|
val frameRate = mLimitedRefreshRate
|
||||||
if (frameRate != null) {
|
if (frameRate != null) {
|
||||||
renderer.limitFrameRate(frameRate)
|
glSurfaceView.setMaxFrameRate(frameRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glSurfaceView.nativeFramePacing = mNativeFramePacing
|
||||||
|
|
||||||
editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
||||||
glSurfaceView.cocos2dxEditText = editText
|
glSurfaceView.cocos2dxEditText = editText
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
glSurfaceView.defaultFocusHighlightEnabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return frameLayout
|
return frameLayout
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,6 +535,8 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mNativeFramePacing = preferenceUtils.getBoolean(PreferenceUtils.Key.NATIVE_FRAME_PACING)
|
||||||
|
|
||||||
if (displayMode == DisplayMode.FULLSCREEN && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (displayMode == DisplayMode.FULLSCREEN && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||||
GeodeUtils.handleSafeArea = true
|
GeodeUtils.handleSafeArea = true
|
||||||
@@ -580,6 +570,10 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
FMOD.close()
|
FMOD.close()
|
||||||
|
|
||||||
|
if (mNativeFramePacing) {
|
||||||
|
LauncherFix.destroyFramePacing()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resumeGame() {
|
private fun resumeGame() {
|
||||||
@@ -751,11 +745,7 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EGLConfigChooser : GLSurfaceView.EGLConfigChooser {
|
class EGLConfigChooser : ExplicitGLSurfaceView.EGLConfigChooser {
|
||||||
// this comes from EGL14, but is unavailable on EGL10
|
|
||||||
// also EGL14 is incompatible with EGL10. so whatever
|
|
||||||
private var EGL_OPENGL_ES2_BIT: Int = 0x04
|
|
||||||
|
|
||||||
private data class ConfigValues(
|
private data class ConfigValues(
|
||||||
val redSize: Int,
|
val redSize: Int,
|
||||||
val greenSize: Int,
|
val greenSize: Int,
|
||||||
@@ -765,29 +755,29 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
val stencilSize: Int,
|
val stencilSize: Int,
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun getAttribValue(egl: EGL10, display: EGLDisplay, config: EGLConfig, attrib: Int): Int {
|
private fun getAttribValue(display: EGLDisplay, config: EGLConfig, attrib: Int): Int {
|
||||||
val value = IntArray(1)
|
val value = IntArray(1)
|
||||||
egl.eglGetConfigAttrib(display, config, attrib, value)
|
EGL14.eglGetConfigAttrib(display, config, attrib, value, 0)
|
||||||
|
|
||||||
return value[0]
|
return value[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun testConfig(egl: EGL10, display: EGLDisplay, attrib: ConfigValues): EGLConfig? {
|
private fun testConfig(display: EGLDisplay, attrib: ConfigValues): EGLConfig? {
|
||||||
val attribList = intArrayOf(
|
val attribList = intArrayOf(
|
||||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
|
||||||
EGL10.EGL_RED_SIZE, attrib.redSize,
|
EGL14.EGL_RED_SIZE, attrib.redSize,
|
||||||
EGL10.EGL_GREEN_SIZE, attrib.greenSize,
|
EGL14.EGL_GREEN_SIZE, attrib.greenSize,
|
||||||
EGL10.EGL_BLUE_SIZE, attrib.blueSize,
|
EGL14.EGL_BLUE_SIZE, attrib.blueSize,
|
||||||
EGL10.EGL_ALPHA_SIZE, attrib.alphaSize,
|
EGL14.EGL_ALPHA_SIZE, attrib.alphaSize,
|
||||||
EGL10.EGL_DEPTH_SIZE, attrib.depthSize,
|
EGL14.EGL_DEPTH_SIZE, attrib.depthSize,
|
||||||
EGL10.EGL_STENCIL_SIZE, attrib.stencilSize,
|
EGL14.EGL_STENCIL_SIZE, attrib.stencilSize,
|
||||||
EGL10.EGL_NONE
|
EGL14.EGL_NONE
|
||||||
)
|
)
|
||||||
|
|
||||||
val configs = arrayOfNulls<EGLConfig>(1)
|
val configs = arrayOfNulls<EGLConfig>(1)
|
||||||
val numConfigs = IntArray(1)
|
val numConfigs = IntArray(1)
|
||||||
|
|
||||||
val res = egl.eglChooseConfig(display, attribList, configs, configs.size, numConfigs)
|
val res = EGL14.eglChooseConfig(display, attribList, 0, configs, 0, configs.size, numConfigs, 0)
|
||||||
if (res && numConfigs[0] > 0 && configs[0] != null) {
|
if (res && numConfigs[0] > 0 && configs[0] != null) {
|
||||||
return configs[0]
|
return configs[0]
|
||||||
}
|
}
|
||||||
@@ -795,18 +785,18 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun printConfig(egl: EGL10, display: EGLDisplay, config: EGLConfig) {
|
private fun printConfig(display: EGLDisplay, config: EGLConfig) {
|
||||||
val id = getAttribValue(egl, display, config, EGL10.EGL_CONFIG_ID)
|
val id = getAttribValue(display, config, EGL14.EGL_CONFIG_ID)
|
||||||
val red = getAttribValue(egl, display, config, EGL10.EGL_RED_SIZE)
|
val red = getAttribValue(display, config, EGL14.EGL_RED_SIZE)
|
||||||
val green = getAttribValue(egl, display, config, EGL10.EGL_GREEN_SIZE)
|
val green = getAttribValue(display, config, EGL14.EGL_GREEN_SIZE)
|
||||||
val blue = getAttribValue(egl, display, config, EGL10.EGL_BLUE_SIZE)
|
val blue = getAttribValue(display, config, EGL14.EGL_BLUE_SIZE)
|
||||||
val alpha = getAttribValue(egl, display, config, EGL10.EGL_ALPHA_SIZE)
|
val alpha = getAttribValue(display, config, EGL14.EGL_ALPHA_SIZE)
|
||||||
val depth = getAttribValue(egl, display, config, EGL10.EGL_DEPTH_SIZE)
|
val depth = getAttribValue(display, config, EGL14.EGL_DEPTH_SIZE)
|
||||||
val stencil = getAttribValue(egl, display, config, EGL10.EGL_STENCIL_SIZE)
|
val stencil = getAttribValue(display, config, EGL14.EGL_STENCIL_SIZE)
|
||||||
println("EGLConfig $id: (red = $red, green = $green, blue = $blue, alpha = $alpha, depth = $depth, stencil = $stencil)")
|
println("EGLConfig $id: (red = $red, green = $green, blue = $blue, alpha = $alpha, depth = $depth, stencil = $stencil)")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chooseConfig(egl: EGL10, display: EGLDisplay): EGLConfig {
|
override fun chooseConfig(display: EGLDisplay): EGLConfig {
|
||||||
val configs = listOf(
|
val configs = listOf(
|
||||||
ConfigValues(8, 8, 8, 8, 16, 8),
|
ConfigValues(8, 8, 8, 8, 16, 8),
|
||||||
ConfigValues(8, 8, 8, 0, 16, 8),
|
ConfigValues(8, 8, 8, 0, 16, 8),
|
||||||
@@ -815,9 +805,9 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
)
|
)
|
||||||
|
|
||||||
return configs.firstNotNullOf {
|
return configs.firstNotNullOf {
|
||||||
val config = testConfig(egl, display, it)
|
val config = testConfig(display, it)
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
printConfig(egl, display, config)
|
printConfig(display, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
config
|
config
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.geode.launcher
|
package com.geode.launcher
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.view.Surface
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.geode.launcher.utils.Constants
|
import com.geode.launcher.utils.Constants
|
||||||
|
|
||||||
@@ -16,4 +18,10 @@ object LauncherFix {
|
|||||||
external fun enableExceptionsRenaming()
|
external fun enableExceptionsRenaming()
|
||||||
|
|
||||||
external fun performPatches()
|
external fun performPatches()
|
||||||
|
|
||||||
|
external fun initFramePacing(activity: Activity)
|
||||||
|
external fun destroyFramePacing()
|
||||||
|
external fun swapFrame(display: Long, surface: Long): Boolean
|
||||||
|
external fun setSurface(surface: Surface?)
|
||||||
|
external fun setSwapInterval(intervalNs: Long)
|
||||||
}
|
}
|
||||||
@@ -104,10 +104,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
val gdInstalled = GamePackageUtils.isGameInstalled(packageManager)
|
val gdInstalled = GamePackageUtils.isGameInstalled(packageManager)
|
||||||
val geodeInstalled = LaunchUtils.isGeodeInstalled(this)
|
val geodeInstalled = LaunchUtils.isGeodeInstalled(this)
|
||||||
|
|
||||||
val restartImmediately = intent.getBooleanExtra("restarted", false)
|
if (gdInstalled && geodeInstalled && intent.getBooleanExtra("restarted", false)) {
|
||||||
if (gdInstalled && geodeInstalled && restartImmediately) {
|
onLaunch(this)
|
||||||
val withSafeMode = intent.getBooleanExtra("safe-mode", false)
|
|
||||||
onLaunch(this, withSafeMode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ import android.provider.DocumentsContract
|
|||||||
import android.provider.DocumentsProvider
|
import android.provider.DocumentsProvider
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import com.geode.launcher.utils.ApplicationIcon
|
|
||||||
import com.geode.launcher.utils.IconUtils
|
|
||||||
import com.geode.launcher.utils.LaunchUtils
|
import com.geode.launcher.utils.LaunchUtils
|
||||||
import com.geode.launcher.utils.PreferenceUtils
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
private val DEFAULT_ROOT_PROJECTION: Array<String> = arrayOf(
|
private val DEFAULT_ROOT_PROJECTION: Array<String> = arrayOf(
|
||||||
@@ -63,17 +60,8 @@ class UserDirectoryProvider : DocumentsProvider() {
|
|||||||
DocumentsContract.Root.FLAG_SUPPORTS_RECENTS or
|
DocumentsContract.Root.FLAG_SUPPORTS_RECENTS or
|
||||||
DocumentsContract.Root.FLAG_SUPPORTS_SEARCH
|
DocumentsContract.Root.FLAG_SUPPORTS_SEARCH
|
||||||
)
|
)
|
||||||
|
add(DocumentsContract.Root.COLUMN_TITLE, context.getString(R.string.app_name))
|
||||||
val selectedIconKey = PreferenceUtils.get(context).getString(PreferenceUtils.Key.SELECTED_ICON)
|
add(DocumentsContract.Root.COLUMN_ICON, R.drawable.geode_logo)
|
||||||
?: "geode"
|
|
||||||
val selectedIcon = ApplicationIcon.fromId(selectedIconKey)
|
|
||||||
val iconDetails = IconUtils.getIconDetails(selectedIcon)
|
|
||||||
|
|
||||||
val nameId = if (selectedIcon == ApplicationIcon.SAPPHIRE) R.string.application_icon_sapphire else R.string.app_name
|
|
||||||
val logoId = if (selectedIcon == ApplicationIcon.GEODE) R.drawable.geode_logo else iconDetails.iconId
|
|
||||||
|
|
||||||
add(DocumentsContract.Root.COLUMN_TITLE, context.getString(nameId))
|
|
||||||
add(DocumentsContract.Root.COLUMN_ICON, logoId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -408,8 +408,7 @@ fun LauncherUpdateIndicator(modifier: Modifier = Modifier) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// there's like a single pixel of the shadow that gets clipped without this...
|
ElevatedCard(modifier) {
|
||||||
ElevatedCard(modifier = modifier.padding(bottom = 1.dp)) {
|
|
||||||
Column(
|
Column(
|
||||||
// buttons add enough padding already, lower to compensate
|
// buttons add enough padding already, lower to compensate
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
|
|||||||
@@ -169,6 +169,12 @@ fun DeveloperSettingsScreen(onBackPressedDispatcher: OnBackPressedDispatcher?) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SettingsCard(
|
||||||
|
title = stringResource(R.string.preference_native_pacing),
|
||||||
|
description = stringResource(R.string.preference_native_pacing_description),
|
||||||
|
preferenceKey = PreferenceUtils.Key.NATIVE_FRAME_PACING,
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
SettingsCard(
|
SettingsCard(
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ object GamePackageUtils {
|
|||||||
39L to "2.206",
|
39L to "2.206",
|
||||||
40L to "2.2074", // ok
|
40L to "2.2074", // ok
|
||||||
41L to "2.2081",
|
41L to "2.2081",
|
||||||
42L to "2.209",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -191,16 +191,10 @@ object GeodeUtils {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun restartGame() {
|
fun restartGame() {
|
||||||
restartGame(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun restartGame(safeMode: Boolean) {
|
|
||||||
activity.get()?.run {
|
activity.get()?.run {
|
||||||
packageManager.getLaunchIntentForPackage(packageName)?.also {
|
packageManager.getLaunchIntentForPackage(packageName)?.also {
|
||||||
val mainIntent = Intent.makeRestartActivityTask(it.component)
|
val mainIntent = Intent.makeRestartActivityTask(it.component)
|
||||||
mainIntent.putExtra("restarted", true)
|
mainIntent.putExtra("restarted", true)
|
||||||
mainIntent.putExtra("safe-mode", safeMode)
|
|
||||||
startActivity(mainIntent)
|
startActivity(mainIntent)
|
||||||
exitProcess(0)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
@@ -800,7 +794,7 @@ object GeodeUtils {
|
|||||||
|
|
||||||
external fun internalKeyEvent(timestamp: Long, deviceId: Int, eventSource: Int, keyCode: Int, modifiers: Int, isDown: Boolean, repeatCount: Int)
|
external fun internalKeyEvent(timestamp: Long, deviceId: Int, eventSource: Int, keyCode: Int, modifiers: Int, isDown: Boolean, repeatCount: Int)
|
||||||
external fun internalTouchEvent(timestamp: Long, deviceId: Int, eventSource: Int, eventType: Int, ids: IntArray, xs: FloatArray, ys: FloatArray)
|
external fun internalTouchEvent(timestamp: Long, deviceId: Int, eventSource: Int, eventType: Int, ids: IntArray, xs: FloatArray, ys: FloatArray)
|
||||||
external fun internalScrollEvent(timestamp: Long, deviceId: Int, eventSource: Int, scrollX: Float, scrollY: Float, mouseX: Float, mouseY: Float)
|
external fun internalScrollEvent(timestamp: Long, deviceId: Int, eventSource: Int, scrollX: Float, scrollY: Float)
|
||||||
external fun internalJoystickEvent(timestamp: Long, deviceId: Int, eventSource: Int, leftX: FloatArray, leftY: FloatArray, rightX: FloatArray, rightY: FloatArray, hatX: FloatArray, hatY: FloatArray, leftTrigger: FloatArray, rightTrigger: FloatArray)
|
external fun internalJoystickEvent(timestamp: Long, deviceId: Int, eventSource: Int, leftX: FloatArray, leftY: FloatArray, rightX: FloatArray, rightY: FloatArray, hatX: FloatArray, hatY: FloatArray, leftTrigger: FloatArray, rightTrigger: FloatArray)
|
||||||
|
|
||||||
external fun inputDeviceAdded(deviceId: Int)
|
external fun inputDeviceAdded(deviceId: Int)
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ enum class ApplicationIcon {
|
|||||||
GEODE,
|
GEODE,
|
||||||
PRIDE,
|
PRIDE,
|
||||||
TRANS,
|
TRANS,
|
||||||
GREEN,
|
|
||||||
SAPPHIRE;
|
SAPPHIRE;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -54,7 +53,6 @@ enum class ApplicationIcon {
|
|||||||
"pride" -> PRIDE
|
"pride" -> PRIDE
|
||||||
"trans" -> TRANS
|
"trans" -> TRANS
|
||||||
"sapphire" -> SAPPHIRE
|
"sapphire" -> SAPPHIRE
|
||||||
"green" -> GREEN
|
|
||||||
else -> DEFAULT
|
else -> DEFAULT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +63,6 @@ enum class ApplicationIcon {
|
|||||||
DEFAULT -> "default"
|
DEFAULT -> "default"
|
||||||
TRANS -> "trans"
|
TRANS -> "trans"
|
||||||
SAPPHIRE -> "sapphire"
|
SAPPHIRE -> "sapphire"
|
||||||
GREEN -> "green"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,11 +105,5 @@ object IconUtils {
|
|||||||
iconId = R.mipmap.ic_launcher_sapphire,
|
iconId = R.mipmap.ic_launcher_sapphire,
|
||||||
nameId = R.string.application_icon_sapphire,
|
nameId = R.string.application_icon_sapphire,
|
||||||
)
|
)
|
||||||
ApplicationIcon.GREEN -> ApplicationIconDetails(
|
|
||||||
id = id.toId(),
|
|
||||||
component = "MainActivityGreen",
|
|
||||||
iconId = R.mipmap.ic_launcher_green,
|
|
||||||
nameId = R.string.application_icon_green,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,6 +150,7 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
|
|||||||
LAST_LAUNCHER_UPDATE,
|
LAST_LAUNCHER_UPDATE,
|
||||||
DISABLE_UPDATE_CACHE,
|
DISABLE_UPDATE_CACHE,
|
||||||
PREBUNDLED_GEODE_MIGRATION_PERFORMED,
|
PREBUNDLED_GEODE_MIGRATION_PERFORMED,
|
||||||
|
NATIVE_FRAME_PACING,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun defaultValueForBooleanKey(key: Key): Boolean {
|
private fun defaultValueForBooleanKey(key: Key): Boolean {
|
||||||
@@ -201,6 +202,7 @@ class PreferenceUtils(private val sharedPreferences: SharedPreferences) {
|
|||||||
Key.LAST_LAUNCHER_UPDATE -> "PreferenceLastLauncherUpdate"
|
Key.LAST_LAUNCHER_UPDATE -> "PreferenceLastLauncherUpdate"
|
||||||
Key.DISABLE_UPDATE_CACHE -> "PreferenceDisableUpdateCache"
|
Key.DISABLE_UPDATE_CACHE -> "PreferenceDisableUpdateCache"
|
||||||
Key.PREBUNDLED_GEODE_MIGRATION_PERFORMED -> "PreferencePrebundledGeodeMigrationPerformed"
|
Key.PREBUNDLED_GEODE_MIGRATION_PERFORMED -> "PreferencePrebundledGeodeMigrationPerformed"
|
||||||
|
Key.NATIVE_FRAME_PACING -> "PreferenceNativeFramePacing"
|
||||||
// Key.RELEASE_CHANNEL -> "PreferenceReleaseChannel"
|
// Key.RELEASE_CHANNEL -> "PreferenceReleaseChannel"
|
||||||
// Key.LAST_DISMISSED_UPDATE -> "PreferenceLastDismissedUpdate"
|
// Key.LAST_DISMISSED_UPDATE -> "PreferenceLastDismissedUpdate"
|
||||||
// Key.FORCE_HRR -> "PreferenceForceHighRefreshRate"
|
// Key.FORCE_HRR -> "PreferenceForceHighRefreshRate"
|
||||||
|
|||||||
@@ -8,73 +8,32 @@ import android.os.Build
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.Message
|
import android.os.Message
|
||||||
import android.text.InputType
|
import android.util.Log
|
||||||
import android.view.InputDevice
|
import android.view.InputDevice
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import android.view.WindowInsets
|
|
||||||
import android.view.inputmethod.EditorInfo
|
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.widget.AppCompatEditText
|
import androidx.appcompat.widget.AppCompatEditText
|
||||||
import com.customRobTop.BaseRobTopActivity
|
import com.customRobTop.BaseRobTopActivity
|
||||||
|
import com.geode.launcher.ExplicitGLSurfaceView
|
||||||
|
import com.geode.launcher.LauncherFix
|
||||||
import com.geode.launcher.utils.GeodeUtils
|
import com.geode.launcher.utils.GeodeUtils
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.roundToLong
|
||||||
|
|
||||||
private const val HANDLER_OPEN_IME_KEYBOARD = 2
|
private const val HANDLER_OPEN_IME_KEYBOARD = 2
|
||||||
private const val HANDLER_CLOSE_IME_KEYBOARD = 3
|
private const val HANDLER_CLOSE_IME_KEYBOARD = 3
|
||||||
private const val MS_TO_NS = 1_000_000
|
private const val MS_TO_NS = 1_000_000
|
||||||
private const val SEC_TO_NS = 1_000_000_000.0
|
private const val SEC_TO_NS = 1_000_000_000.0
|
||||||
|
|
||||||
fun inputTypeForFlags(i: Int): Int {
|
class Cocos2dxGLSurfaceView(context: Context) : ExplicitGLSurfaceView(context) {
|
||||||
if ((i and BaseRobTopActivity.KEYBOARD_INPUT_NUMERIC) != 0) {
|
|
||||||
return InputType.TYPE_NUMBER_FLAG_DECIMAL or InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_NUMBER
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((i and BaseRobTopActivity.KEYBOARD_INPUT_PASSWORD) != 0) {
|
|
||||||
return InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((i and BaseRobTopActivity.KEYBOARD_INPUT_MULTILINE) != 0) {
|
|
||||||
return InputType.TYPE_TEXT_FLAG_MULTI_LINE or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or InputType.TYPE_CLASS_TEXT
|
|
||||||
}
|
|
||||||
|
|
||||||
return InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS or InputType.TYPE_CLASS_TEXT
|
|
||||||
}
|
|
||||||
|
|
||||||
fun usesInlineKeyboard(): Boolean {
|
|
||||||
return Build.VERSION.SDK_INT >= 30
|
|
||||||
}
|
|
||||||
|
|
||||||
fun imeOptionsForFlags(i: Int): Int {
|
|
||||||
val i2 = if ((i and BaseRobTopActivity.KEYBOARD_INPUT_MULTILINE) == 0 || !usesInlineKeyboard())
|
|
||||||
EditorInfo.IME_ACTION_DONE else EditorInfo.IME_ACTION_NONE
|
|
||||||
|
|
||||||
return if (usesInlineKeyboard())
|
|
||||||
EditorInfo.IME_FLAG_NO_FULLSCREEN or EditorInfo.IME_FLAG_NO_EXTRACT_UI or i2
|
|
||||||
else i2
|
|
||||||
}
|
|
||||||
|
|
||||||
class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var cocos2dxGLSurfaceView: Cocos2dxGLSurfaceView
|
lateinit var cocos2dxGLSurfaceView: Cocos2dxGLSurfaceView
|
||||||
private lateinit var handler: Handler
|
private lateinit var handler: Handler
|
||||||
private lateinit var cocos2dxTextInputWrapper: Cocos2dxTextInputWrapper
|
private lateinit var cocos2dxTextInputWrapper: Cocos2dxTextInputWrapper
|
||||||
|
|
||||||
private var keyboardVisible = false
|
|
||||||
private var keyboardHeight = 0
|
|
||||||
|
|
||||||
private var keyboardHideCheck = Runnable {
|
|
||||||
if (keyboardVisible) {
|
|
||||||
return@Runnable
|
|
||||||
}
|
|
||||||
|
|
||||||
cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
cocos2dxGLSurfaceView.cocos2dxRenderer.handleTextClosed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun openIMEKeyboard() {
|
fun openIMEKeyboard() {
|
||||||
val msg = Message()
|
val msg = Message()
|
||||||
@@ -94,30 +53,6 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
cocos2dxGLSurfaceView.queueEvent {
|
cocos2dxGLSurfaceView.queueEvent {
|
||||||
Cocos2dxAccelerometer.onSensorChanged(x, y, z, timestamp)
|
Cocos2dxAccelerometer.onSensorChanged(x, y, z, timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
|
||||||
fun onKeyboardInsets(windowInsets: WindowInsets) {
|
|
||||||
if (!cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val visible = windowInsets.isVisible(WindowInsets.Type.ime())
|
|
||||||
val offsetHeight = if (visible) windowInsets.getInsets(WindowInsets.Type.ime()).bottom else 0
|
|
||||||
|
|
||||||
if (visible == keyboardVisible && offsetHeight == keyboardHeight) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboardVisible = visible
|
|
||||||
keyboardHeight = offsetHeight
|
|
||||||
|
|
||||||
handler.removeCallbacks(keyboardHideCheck)
|
|
||||||
if (!visible) {
|
|
||||||
handler.postDelayed(keyboardHideCheck, 150L)
|
|
||||||
} else {
|
|
||||||
cocos2dxGLSurfaceView.cocos2dxRenderer.handleKeyboardWillShow(keyboardHeight)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var cocos2dxRenderer: Cocos2dxRenderer
|
private lateinit var cocos2dxRenderer: Cocos2dxRenderer
|
||||||
@@ -132,9 +67,7 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
var controllerEventsEnabled = false
|
var controllerEventsEnabled = false
|
||||||
private set
|
private set
|
||||||
var supportsResizeEvents = false
|
var supportsResizeEvents = false
|
||||||
|
var saveNativeFramePacing = false
|
||||||
// 2.209+ events for keyboard and such
|
|
||||||
var sendNewCocosEvents = false
|
|
||||||
|
|
||||||
var cocos2dxEditText: AppCompatEditText? = null
|
var cocos2dxEditText: AppCompatEditText? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -156,13 +89,9 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
HANDLER_OPEN_IME_KEYBOARD -> {
|
HANDLER_OPEN_IME_KEYBOARD -> {
|
||||||
if (cocos2dxEditText?.requestFocus() == true) {
|
if (cocos2dxEditText?.requestFocus() == true) {
|
||||||
cocos2dxEditText?.apply {
|
cocos2dxEditText?.apply {
|
||||||
removeTextChangedListener(cocos2dxTextInputWrapper)
|
removeTextChangedListener(
|
||||||
|
cocos2dxTextInputWrapper
|
||||||
if (sendNewCocosEvents) {
|
)
|
||||||
inputType = inputTypeForFlags(BaseRobTopActivity.curKeyboardInputFlags)
|
|
||||||
imeOptions = imeOptionsForFlags(BaseRobTopActivity.curKeyboardInputFlags)
|
|
||||||
}
|
|
||||||
|
|
||||||
setText("")
|
setText("")
|
||||||
val text = msg.obj as String
|
val text = msg.obj as String
|
||||||
append(text)
|
append(text)
|
||||||
@@ -175,13 +104,16 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
cocos2dxEditText,
|
cocos2dxEditText,
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
|
Log.d("GLSurfaceView", "showSoftInput")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
HANDLER_CLOSE_IME_KEYBOARD -> {
|
HANDLER_CLOSE_IME_KEYBOARD -> {
|
||||||
cocos2dxEditText?.apply {
|
cocos2dxEditText?.apply {
|
||||||
removeTextChangedListener(cocos2dxTextInputWrapper)
|
removeTextChangedListener(
|
||||||
|
cocos2dxTextInputWrapper
|
||||||
|
)
|
||||||
(context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(
|
(context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(
|
||||||
windowToken,
|
windowToken,
|
||||||
0
|
0
|
||||||
@@ -189,10 +121,8 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestFocus()
|
requestFocus()
|
||||||
|
Log.d("GLSurfaceView", "HideSoftInput")
|
||||||
queueEvent {
|
cocos2dxRenderer.handleTextClosed()
|
||||||
cocos2dxRenderer.handleTextClosed()
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
else -> return
|
else -> return
|
||||||
@@ -213,6 +143,10 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
|
|
||||||
println("updateRefreshRate: selecting refresh rate of ${chosenDisplay.refreshRate} (display ${chosenDisplay.modeId})")
|
println("updateRefreshRate: selecting refresh rate of ${chosenDisplay.refreshRate} (display ${chosenDisplay.modeId})")
|
||||||
|
|
||||||
|
if (saveNativeFramePacing) {
|
||||||
|
LauncherFix.setSwapInterval((1_000_000_000L / chosenRefreshRate).roundToLong())
|
||||||
|
}
|
||||||
|
|
||||||
holder.surface.setFrameRate(chosenRefreshRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT)
|
holder.surface.setFrameRate(chosenRefreshRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT)
|
||||||
if (isAttachedToWindow) {
|
if (isAttachedToWindow) {
|
||||||
(context as Activity).window.attributes.preferredRefreshRate = chosenRefreshRate
|
(context as Activity).window.attributes.preferredRefreshRate = chosenRefreshRate
|
||||||
@@ -227,6 +161,7 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
renderMode = RENDERMODE_CONTINUOUSLY
|
renderMode = RENDERMODE_CONTINUOUSLY
|
||||||
queueEvent { cocos2dxRenderer.handleOnResume() }
|
queueEvent { cocos2dxRenderer.handleOnResume() }
|
||||||
}
|
}
|
||||||
@@ -371,97 +306,6 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun queueKeyboardEvent(keyCode: Int, event: KeyEvent, down: Boolean): Boolean {
|
|
||||||
val keypadCode = keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK
|
|
||||||
if (event.isSystem && !keypadCode) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keypadCode && BaseRobTopActivity.blockBackButton) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
queueEvent {
|
|
||||||
sendNextEventTimestamp(event.eventTime * MS_TO_NS)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useKeyboardEvents) {
|
|
||||||
if (down) {
|
|
||||||
queueEvent {
|
|
||||||
GeodeUtils.nativeKeyDown(keyCode, event.modifiers, event.repeatCount != 0)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
queueEvent {
|
|
||||||
GeodeUtils.nativeKeyUp(keyCode, event.modifiers)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controllerEventsEnabled) {
|
|
||||||
queueEvent {
|
|
||||||
GeodeUtils.internalKeyEvent(
|
|
||||||
event.eventTime * MS_TO_NS,
|
|
||||||
event.deviceId,
|
|
||||||
event.source,
|
|
||||||
event.keyCode,
|
|
||||||
event.modifiers,
|
|
||||||
down,
|
|
||||||
event.repeatCount
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// geode events override native callbacks
|
|
||||||
if (useKeyboardEvents || controllerEventsEnabled) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sendNewCocosEvents) {
|
|
||||||
if (KeyEvent.isGamepadButton(keyCode)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyCode == KeyEvent.KEYCODE_ESCAPE && BaseRobTopActivity.blockBackButton) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// messy logic
|
|
||||||
val isRepeat = event.repeatCount > 0
|
|
||||||
if (keypadCode) {
|
|
||||||
if (down) {
|
|
||||||
if (isRepeat || BaseRobTopActivity.blockBackButton) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
queueEvent {
|
|
||||||
cocos2dxRenderer.handleKeyDown(keyCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val eventTimestamp = event.eventTime / 1000.0
|
|
||||||
|
|
||||||
val shiftPressed = event.isShiftPressed
|
|
||||||
val ctrlPressed = event.isCtrlPressed
|
|
||||||
val altPressed = event.isAltPressed
|
|
||||||
|
|
||||||
queueEvent {
|
|
||||||
cocos2dxRenderer.handleKeyboardEvent(
|
|
||||||
keyCode, down, isRepeat, eventTimestamp,
|
|
||||||
shiftPressed, ctrlPressed, altPressed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun legacyKeyDown(keyCode: Int, keyEvent: KeyEvent): Boolean {
|
private fun legacyKeyDown(keyCode: Int, keyEvent: KeyEvent): Boolean {
|
||||||
return when (keyCode) {
|
return when (keyCode) {
|
||||||
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_MENU -> {
|
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_MENU -> {
|
||||||
@@ -519,19 +363,65 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||||
if (!queueKeyboardEvent(keyCode, event, true)) {
|
if (!useKeyboardEvents && !controllerEventsEnabled) {
|
||||||
return legacyKeyDown(keyCode, event)
|
return legacyKeyDown(keyCode, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return when (keyCode) {
|
||||||
|
// ignore system keys
|
||||||
|
KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_MUTE -> {
|
||||||
|
super.onKeyDown(keyCode, event)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
if (BaseRobTopActivity.blockBackButton) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
queueEvent {
|
||||||
|
sendNextEventTimestamp(event.eventTime * MS_TO_NS)
|
||||||
|
|
||||||
|
if (useKeyboardEvents) {
|
||||||
|
GeodeUtils.nativeKeyDown(keyCode, event.modifiers, event.repeatCount != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controllerEventsEnabled) {
|
||||||
|
GeodeUtils.internalKeyEvent(event.eventTime * MS_TO_NS, event.deviceId, event.source, event.keyCode, event.modifiers, true, event.repeatCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
||||||
if (!queueKeyboardEvent(keyCode, event, false)) {
|
if (!useKeyboardEvents && !controllerEventsEnabled) {
|
||||||
return super.onKeyUp(keyCode, event)
|
return super.onKeyUp(keyCode, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return when (keyCode) {
|
||||||
|
KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_MUTE -> {
|
||||||
|
super.onKeyUp(keyCode, event)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
if (event.repeatCount != 0 || BaseRobTopActivity.blockBackButton) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
queueEvent {
|
||||||
|
sendNextEventTimestamp(event.eventTime * MS_TO_NS)
|
||||||
|
|
||||||
|
if (useKeyboardEvents) {
|
||||||
|
GeodeUtils.nativeKeyUp(keyCode, event.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controllerEventsEnabled) {
|
||||||
|
GeodeUtils.internalKeyEvent(event.eventTime * MS_TO_NS, event.deviceId, event.source, event.keyCode, event.modifiers, false, event.repeatCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// i'm lazy.
|
// i'm lazy.
|
||||||
@@ -594,15 +484,11 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onGenericMotionEvent(event: MotionEvent?): Boolean {
|
override fun onGenericMotionEvent(event: MotionEvent?): Boolean {
|
||||||
val hasGeodeEvents = useKeyboardEvents || controllerEventsEnabled
|
if (!useKeyboardEvents && !controllerEventsEnabled) {
|
||||||
if (!hasGeodeEvents && !sendNewCocosEvents) {
|
|
||||||
return super.onGenericMotionEvent(event)
|
return super.onGenericMotionEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event?.action == MotionEvent.ACTION_SCROLL) {
|
if (event?.action == MotionEvent.ACTION_SCROLL) {
|
||||||
val mouseX = event.x
|
|
||||||
val mouseY = event.y
|
|
||||||
|
|
||||||
val scrollX = event.getAxisValue(MotionEvent.AXIS_HSCROLL)
|
val scrollX = event.getAxisValue(MotionEvent.AXIS_HSCROLL)
|
||||||
val scrollY = event.getAxisValue(MotionEvent.AXIS_VSCROLL)
|
val scrollY = event.getAxisValue(MotionEvent.AXIS_VSCROLL)
|
||||||
val timestamp = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
val timestamp = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||||
@@ -616,11 +502,7 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (controllerEventsEnabled) {
|
if (controllerEventsEnabled) {
|
||||||
GeodeUtils.internalScrollEvent(timestamp, event.deviceId, event.source, scrollX, scrollY, mouseX, mouseY)
|
GeodeUtils.internalScrollEvent(timestamp, event.deviceId, event.source, scrollX, scrollY)
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasGeodeEvents && sendNewCocosEvents) {
|
|
||||||
cocos2dxRenderer.handleScroll(mouseX, mouseY, scrollY, scrollX)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,6 +542,11 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
setRenderer(this.cocos2dxRenderer)
|
setRenderer(this.cocos2dxRenderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setNativeFramePacing(nativeFramePacing: Boolean) {
|
||||||
|
super.setNativeFramePacing(nativeFramePacing)
|
||||||
|
saveNativeFramePacing = nativeFramePacing
|
||||||
|
}
|
||||||
|
|
||||||
private fun getContentText(): String {
|
private fun getContentText(): String {
|
||||||
return cocos2dxRenderer.getContentText()
|
return cocos2dxRenderer.getContentText()
|
||||||
}
|
}
|
||||||
@@ -694,6 +581,10 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
inputManager.unregisterInputDeviceListener(InputListener)
|
inputManager.unregisterInputDeviceListener(InputListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setMaxFrameRate(rate: Int) {
|
||||||
|
cocos2dxRenderer.limitFrameRate(rate)
|
||||||
|
}
|
||||||
|
|
||||||
object InputListener : InputManager.InputDeviceListener {
|
object InputListener : InputManager.InputDeviceListener {
|
||||||
override fun onInputDeviceAdded(deviceId: Int) {
|
override fun onInputDeviceAdded(deviceId: Int) {
|
||||||
GeodeUtils.inputDeviceAdded(deviceId)
|
GeodeUtils.inputDeviceAdded(deviceId)
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package org.cocos2dx.lib
|
package org.cocos2dx.lib
|
||||||
|
|
||||||
import android.opengl.GLSurfaceView
|
import android.opengl.EGLConfig
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import javax.microedition.khronos.egl.EGLConfig
|
import com.geode.launcher.ExplicitGLSurfaceView
|
||||||
import javax.microedition.khronos.opengles.GL10
|
|
||||||
|
|
||||||
private const val NANOSECONDS_PER_SECOND = 1000000000L
|
private const val NANOSECONDS_PER_SECOND = 1000000000L
|
||||||
private const val NANOSECONDS_PER_MICROSECOND = 1000000L
|
private const val NANOSECONDS_PER_MICROSECOND = 1000000L
|
||||||
|
|
||||||
@Suppress("unused", "KotlinJniMissingFunction")
|
@Suppress("unused", "KotlinJniMissingFunction")
|
||||||
class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceView.Renderer {
|
class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : ExplicitGLSurfaceView.Renderer {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setAnimationInterval(@Suppress("UNUSED_PARAMETER") animationInterval: Double) {
|
fun setAnimationInterval(@Suppress("UNUSED_PARAMETER") animationInterval: Double) {
|
||||||
@@ -28,29 +27,12 @@ class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceVi
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
private external fun nativeKeyDown(keyCode: Int): Boolean
|
private external fun nativeKeyDown(keyCode: Int): Boolean
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
private external fun nativeKeyboardEvent(
|
|
||||||
keyCode: Int,
|
|
||||||
down: Boolean,
|
|
||||||
isRepeat: Boolean,
|
|
||||||
timestamp: Double,
|
|
||||||
shiftPressed: Boolean,
|
|
||||||
ctrlPressed: Boolean,
|
|
||||||
altPressed: Boolean
|
|
||||||
)
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
private external fun nativeKeyboardWillShow(offset: Int)
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private external fun nativeOnPause()
|
private external fun nativeOnPause()
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private external fun nativeOnResume()
|
private external fun nativeOnResume()
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
private external fun nativeScroll(x: Float, y: Float, scrollY: Float, scrollX: Float)
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private external fun nativeRender()
|
private external fun nativeRender()
|
||||||
|
|
||||||
@@ -97,12 +79,12 @@ class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceVi
|
|||||||
screenHeight = surfaceHeight
|
screenHeight = surfaceHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSurfaceCreated(gl10: GL10?, eglConfig: EGLConfig?) {
|
override fun onSurfaceCreated(eglConfig: EGLConfig?) {
|
||||||
nativeInit(screenWidth, screenHeight)
|
nativeInit(screenWidth, screenHeight)
|
||||||
lastTickInNanoSeconds = System.nanoTime()
|
lastTickInNanoSeconds = System.nanoTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSurfaceChanged(gl10: GL10?, width: Int, height: Int) {
|
override fun onSurfaceChanged(width: Int, height: Int) {
|
||||||
if (setFrameRate && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (setFrameRate && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
handler.updateRefreshRate()
|
handler.updateRefreshRate()
|
||||||
}
|
}
|
||||||
@@ -110,7 +92,7 @@ class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceVi
|
|||||||
println("renderer surfaceChanged: ${width}x${height}@${handler.display.refreshRate}fps")
|
println("renderer surfaceChanged: ${width}x${height}@${handler.display.refreshRate}fps")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDrawFrame(gl: GL10?) {
|
override fun onDrawFrame() {
|
||||||
val animationInterval = mAnimationInterval
|
val animationInterval = mAnimationInterval
|
||||||
if (animationInterval == null) {
|
if (animationInterval == null) {
|
||||||
nativeRender()
|
nativeRender()
|
||||||
@@ -150,18 +132,6 @@ class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceVi
|
|||||||
nativeKeyDown(keyCode)
|
nativeKeyDown(keyCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleKeyboardWillShow(offset: Int) {
|
|
||||||
nativeKeyboardWillShow(offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun handleKeyboardEvent(keyCode: Int, down: Boolean, isRepeat: Boolean, timestamp: Double, shiftPressed: Boolean, ctrlPressed: Boolean, altPressed: Boolean) {
|
|
||||||
nativeKeyboardEvent(keyCode, down, isRepeat, timestamp, shiftPressed, ctrlPressed, altPressed)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun handleScroll(x: Float, y: Float, scrollY: Float, scrollX: Float) {
|
|
||||||
nativeScroll(x, y, scrollY, scrollX)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun handleOnPause() {
|
fun handleOnPause() {
|
||||||
nativeOnPause()
|
nativeOnPause()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ import android.text.TextWatcher
|
|||||||
import android.widget.TextView.OnEditorActionListener
|
import android.widget.TextView.OnEditorActionListener
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.inputmethod.EditorInfo
|
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.customRobTop.JniToCpp
|
|
||||||
|
|
||||||
class Cocos2dxTextInputWrapper(private val cocos2dxGLSurfaceView: Cocos2dxGLSurfaceView) : TextWatcher, OnEditorActionListener {
|
class Cocos2dxTextInputWrapper(private val cocos2dxGLSurfaceView: Cocos2dxGLSurfaceView) : TextWatcher, OnEditorActionListener {
|
||||||
private var originText: String? = null
|
private var originText: String? = null
|
||||||
@@ -21,33 +19,21 @@ class Cocos2dxTextInputWrapper(private val cocos2dxGLSurfaceView: Cocos2dxGLSurf
|
|||||||
this.originText = originText
|
this.originText = originText
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterTextChanged(editable: Editable) {
|
override fun afterTextChanged(s: Editable) {
|
||||||
if (isFullScreenEdit) {
|
if (!isFullScreenEdit) {
|
||||||
return
|
var nModified = s.length - text!!.length
|
||||||
|
if (nModified > 0) {
|
||||||
|
cocos2dxGLSurfaceView.insertText(
|
||||||
|
s.subSequence(text!!.length, s.length).toString()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
while (nModified < 0) {
|
||||||
|
cocos2dxGLSurfaceView.deleteBackward()
|
||||||
|
nModified++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text = s.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
val cText = text ?: return
|
|
||||||
|
|
||||||
val str = editable.toString()
|
|
||||||
val unchanged = str.commonPrefixWith(cText)
|
|
||||||
|
|
||||||
var unchangedUntil = unchanged.length
|
|
||||||
if (unchangedUntil > 0 && unchangedUntil < str.length && Character.isLowSurrogate(str[unchangedUntil])) {
|
|
||||||
unchangedUntil--
|
|
||||||
}
|
|
||||||
|
|
||||||
val codePointLength = cText.codePointCount(unchangedUntil, cText.length)
|
|
||||||
repeat(codePointLength) {
|
|
||||||
cocos2dxGLSurfaceView.deleteBackward()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unchangedUntil < str.length) {
|
|
||||||
cocos2dxGLSurfaceView.insertText(
|
|
||||||
str.substring(unchangedUntil)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
text = str
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(
|
override fun beforeTextChanged(
|
||||||
@@ -61,45 +47,22 @@ class Cocos2dxTextInputWrapper(private val cocos2dxGLSurfaceView: Cocos2dxGLSurf
|
|||||||
|
|
||||||
override fun onTextChanged(pCharSequence: CharSequence, start: Int, before: Int, count: Int) {}
|
override fun onTextChanged(pCharSequence: CharSequence, start: Int, before: Int, count: Int) {}
|
||||||
override fun onEditorAction(textView: TextView, actionID: Int, keyEvent: KeyEvent?): Boolean {
|
override fun onEditorAction(textView: TextView, actionID: Int, keyEvent: KeyEvent?): Boolean {
|
||||||
val fullscreenIme = cocos2dxGLSurfaceView.cocos2dxEditText == textView && isFullScreenEdit
|
if (cocos2dxGLSurfaceView.cocos2dxEditText == textView && isFullScreenEdit) {
|
||||||
if (fullscreenIme) {
|
for (i in originText!!.length downTo 1) {
|
||||||
|
cocos2dxGLSurfaceView.deleteBackward()
|
||||||
|
}
|
||||||
var text = textView.text.toString()
|
var text = textView.text.toString()
|
||||||
if (originText != text || !cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
if (!text.endsWith('\n')) {
|
||||||
if (cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
text += '\n'
|
||||||
cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
JniToCpp.textInputCaretToEnd()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repeat(originText!!.length) {
|
|
||||||
cocos2dxGLSurfaceView.deleteBackward()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
|
||||||
if (!text.endsWith('\n')) {
|
|
||||||
text += '\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text.isNotEmpty()) {
|
|
||||||
cocos2dxGLSurfaceView.insertText(text)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (fullscreenIme || actionID == EditorInfo.IME_ACTION_DONE) {
|
cocos2dxGLSurfaceView.insertText(text)
|
||||||
if (cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
|
||||||
cocos2dxGLSurfaceView.queueEvent {
|
|
||||||
JniToCpp.textInputDone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (actionID != 6) {
|
||||||
if (actionID == EditorInfo.IME_ACTION_DONE) {
|
return false
|
||||||
cocos2dxGLSurfaceView.requestFocus()
|
|
||||||
Cocos2dxGLSurfaceView.closeIMEKeyboard()
|
|
||||||
}
|
}
|
||||||
|
cocos2dxGLSurfaceView.requestFocus()
|
||||||
|
Cocos2dxGLSurfaceView.closeIMEKeyboard()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,28 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="1366"
|
android:viewportWidth="1024"
|
||||||
android:viewportHeight="1366">
|
android:viewportHeight="1024">
|
||||||
<group>
|
<group android:scaleX="0.75" android:scaleY="0.75" android:translateX="128" android:translateY="128">
|
||||||
<clip-path
|
<clip-path
|
||||||
android:pathData="M0,0h1366v1366h-1366z"/>
|
android:pathData="M0,0h1024v1024h-1024z"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M0,0h1366v1366h-1366z"
|
android:pathData="M0,0h1024v1024h-1024z"
|
||||||
android:fillColor="#F4D48E"/>
|
android:fillColor="#F4D48E"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M598,683m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
android:pathData="M512,512m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
||||||
android:fillColor="#F4D48E"/>
|
android:fillColor="#F4D48E"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M873.8,459.7C752.5,412.3 642.7,323 397.2,323C151.8,323 18.6,418.7 4.3,463.8C-10.1,508.8 4.7,562.4 -1.7,561.4L-25,878H1382L1373,631.1C1346.8,597.8 1260.8,569.9 1217.2,562.4C1173.6,554.9 996.8,507.8 873.8,459.7Z"
|
android:pathData="M719.5,289C618,241.7 526,152.5 320.5,152.5C115,152.5 3.5,248 -8.5,293C-20.5,338 -8.2,391.5 -13.5,390.5L-33,706.5H1145L1137.5,460C1115.5,426.8 1043.5,399 1007,391.5C970.5,384 822.5,337 719.5,289Z"
|
||||||
android:fillColor="#F4A47B"/>
|
android:fillColor="#F4A47B"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M647.9,685.4C569.9,647.4 412.4,573 277.3,573C142.1,573 80.5,611.7 39.1,632.4C-2.4,653.2 -9.5,656.1 -14.9,657.4L-25,978.5L650,985L647.9,685.4Z"
|
android:pathData="M561.5,514.5C488.5,476.5 341,402 214.5,402C88,402 30.3,440.7 -8.5,461.5C-47.3,482.3 -54,485.2 -59,486.5L-68.5,808L563.5,814.5L561.5,514.5Z"
|
||||||
android:fillColor="#E27880"/>
|
android:fillColor="#E27880"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1362.1,728.7C1327,696.7 1194.3,624.7 888.5,623C725.4,622.1 492.3,679.9 354.7,757.1C228.9,827.6 68.9,867 -5.2,873.5L-152,1140H1583L1362.1,728.7Z"
|
android:pathData="M1020.5,551C994,521.2 893.7,454.1 662.5,452.5C539.2,451.6 363,505.6 259,577.5C163.9,643.2 43,680 -13,686L-124,934.5H1187.5L1020.5,551Z"
|
||||||
android:fillColor="#B9588F"/>
|
android:fillColor="#B9588F"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1107,1027.2C885.5,1027.2 739,943.6 544.9,943.6C350.9,943.6 228.8,1031.7 186.1,1040.2L-8,1120.8V1385L1376,1379L1367,909C1361.5,929 1287.6,1027.2 1107,1027.2Z"
|
android:pathData="M819.5,856C638,856 518,772.5 359,772.5C200,772.5 100,860.5 65,869L-94,949.5V1041.5L1177.5,1025.5L1032.5,738C1028,758 967.4,856 819.5,856Z"
|
||||||
android:fillColor="#714A9A"/>
|
android:fillColor="#714A9A"/>
|
||||||
</group>
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="1366"
|
|
||||||
android:viewportHeight="1366">
|
|
||||||
<group>
|
|
||||||
<clip-path
|
|
||||||
android:pathData="M0,0h1366v1366h-1366z"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M0,0h1366v1366h-1366z"
|
|
||||||
android:fillColor="#9EF4C3"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M598,683m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
|
||||||
android:fillColor="#9EF4C3"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M873.8,459.7C752.5,412.3 642.7,323 397.2,323C151.8,323 18.6,418.7 4.3,463.8C-10.1,508.8 4.7,562.4 -1.7,561.4L-25,878H1382L1373,631.1C1346.8,597.8 1260.8,569.9 1217.2,562.4C1173.6,554.9 996.8,507.8 873.8,459.7Z"
|
|
||||||
android:fillColor="#6DDBAD"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M647.9,685.4C569.9,647.4 412.4,573 277.3,573C142.1,573 80.5,611.7 39.1,632.4C-2.4,653.2 -9.5,656.1 -14.9,657.4L-25,978.5L650,985L647.9,685.4Z"
|
|
||||||
android:fillColor="#64C780"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M1362.1,728.7C1327,696.7 1194.3,624.7 888.5,623C725.4,622.1 492.3,679.9 354.7,757.1C228.9,827.6 68.9,867 -5.2,873.5L-152,1140H1583L1362.1,728.7Z"
|
|
||||||
android:fillColor="#46A47D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M1107,1027.2C885.5,1027.2 739,943.6 544.9,943.6C350.9,943.6 228.8,1031.7 186.1,1040.2L-8,1120.8V1385L1376,1379L1367,909C1361.5,929 1287.6,1027.2 1107,1027.2Z"
|
|
||||||
android:fillColor="#417563"/>
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
|
|
||||||
@@ -1,29 +1,28 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="1366"
|
android:viewportWidth="1024"
|
||||||
android:viewportHeight="1366">
|
android:viewportHeight="1024">
|
||||||
<group>
|
<group android:scaleX="0.75" android:scaleY="0.75" android:translateX="128" android:translateY="128">
|
||||||
<clip-path
|
<clip-path
|
||||||
android:pathData="M0,0h1366v1366h-1366z"/>
|
android:pathData="M0,0h1024v1024h-1024z"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M0,0h1366v1366h-1366z"
|
android:pathData="M0,0h1024v1024h-1024z"
|
||||||
android:fillColor="#CC7C7C"/>
|
android:fillColor="#CC7C7C"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M598,683m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
android:pathData="M512,512m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
||||||
android:fillColor="#CC7C7C"/>
|
android:fillColor="#CC7C7C"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M873.8,459.7C752.5,412.3 642.7,323 397.2,323C151.8,323 18.6,418.7 4.3,463.8C-10.1,508.8 4.7,562.4 -1.7,561.4L-25,878H1382L1373,631.1C1346.8,597.8 1260.8,569.9 1217.2,562.4C1173.6,554.9 996.8,507.8 873.8,459.7Z"
|
android:pathData="M719.5,289C618,241.7 526,152.5 320.5,152.5C115,152.5 3.5,248 -8.5,293C-20.5,338 -8.2,391.5 -13.5,390.5L-33,706.5H1145L1137.5,460C1115.5,426.8 1043.5,399 1007,391.5C970.5,384 822.5,337 719.5,289Z"
|
||||||
android:fillColor="#C6B471"/>
|
android:fillColor="#C6B471"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M647.9,685.4C569.9,647.4 412.4,573 277.3,573C142.1,573 80.5,611.7 39.1,632.4C-2.4,653.2 -9.5,656.1 -14.9,657.4L-25,978.5L650,985L647.9,685.4Z"
|
android:pathData="M561.5,514.5C488.5,476.5 341,402 214.5,402C88,402 30.3,440.7 -8.5,461.5C-47.3,482.3 -54,485.2 -59,486.5L-68.5,808L563.5,814.5L561.5,514.5Z"
|
||||||
android:fillColor="#59AF7F"/>
|
android:fillColor="#59AF7F"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1362.1,728.7C1327,696.7 1194.3,624.7 888.5,623C725.4,622.1 492.3,679.9 354.7,757.1C228.9,827.6 68.9,867 -5.2,873.5L-152,1140H1583L1362.1,728.7Z"
|
android:pathData="M1020.5,551C994,521.2 893.7,454.1 662.5,452.5C539.2,451.6 363,505.6 259,577.5C163.9,643.2 43,680 -13,686L-124,934.5H1187.5L1020.5,551Z"
|
||||||
android:fillColor="#5F8CAB"/>
|
android:fillColor="#5F8CAB"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1107,1027.2C885.5,1027.2 739,943.6 544.9,943.6C350.9,943.6 228.8,1031.7 186.1,1040.2L-8,1120.8V1385L1376,1379L1367,909C1361.5,929 1287.6,1027.2 1107,1027.2Z"
|
android:pathData="M819.5,856C638,856 518,772.5 359,772.5C200,772.5 100,860.5 65,869L-94,949.5V1041.5L1177.5,1025.5L1032.5,738C1028,758 967.4,856 819.5,856Z"
|
||||||
android:fillColor="#70558D"/>
|
android:fillColor="#70558D"/>
|
||||||
</group>
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
||||||
@@ -1,29 +1,28 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="1366"
|
android:viewportWidth="1024"
|
||||||
android:viewportHeight="1366">
|
android:viewportHeight="1024">
|
||||||
<group>
|
<group android:scaleX="0.75" android:scaleY="0.75" android:translateX="128" android:translateY="128">
|
||||||
<clip-path
|
<clip-path
|
||||||
android:pathData="M0,0h1366v1366h-1366z"/>
|
android:pathData="M0,0h1024v1024h-1024z"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M0,0h1366v1366h-1366z"
|
android:pathData="M0,0h1024v1024h-1024z"
|
||||||
android:fillColor="#65B8C2"/>
|
android:fillColor="#65B8C2"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M598,683m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
android:pathData="M512,512m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
||||||
android:fillColor="#65B8C2"/>
|
android:fillColor="#65B8C2"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M873.8,459.7C752.5,412.3 642.7,323 397.2,323C151.8,323 18.6,418.7 4.3,463.8C-10.1,508.8 4.7,562.4 -1.7,561.4L-25,878H1382L1373,631.1C1346.8,597.8 1260.8,569.9 1217.2,562.4C1173.6,554.9 996.8,507.8 873.8,459.7Z"
|
android:pathData="M719.5,289C618,241.7 526,152.5 320.5,152.5C115,152.5 3.5,248 -8.5,293C-20.5,338 -8.2,391.5 -13.5,390.5L-33,706.5H1145L1137.5,460C1115.5,426.8 1043.5,399 1007,391.5C970.5,384 822.5,337 719.5,289Z"
|
||||||
android:fillColor="#DEA5CD"/>
|
android:fillColor="#DEA5CD"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M647.9,685.4C569.9,647.4 412.4,573 277.3,573C142.1,573 80.5,611.7 39.1,632.4C-2.4,653.2 -9.5,656.1 -14.9,657.4L-25,978.5L650,985L647.9,685.4Z"
|
android:pathData="M561.5,514.5C488.5,476.5 341,402 214.5,402C88,402 30.3,440.7 -8.5,461.5C-47.3,482.3 -54,485.2 -59,486.5L-68.5,808L563.5,814.5L561.5,514.5Z"
|
||||||
android:fillColor="#DEE8EA"/>
|
android:fillColor="#DEE8EA"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1362.1,728.7C1327,696.7 1194.3,624.7 888.5,623C725.4,622.1 492.3,679.9 354.7,757.1C228.9,827.6 68.9,867 -5.2,873.5L-152,1140H1583L1362.1,728.7Z"
|
android:pathData="M1020.5,551C994,521.2 893.7,454.1 662.5,452.5C539.2,451.6 363,505.6 259,577.5C163.9,643.2 43,680 -13,686L-124,934.5H1187.5L1020.5,551Z"
|
||||||
android:fillColor="#C485BD"/>
|
android:fillColor="#C485BD"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1107,1027.2C885.5,1027.2 739,943.6 544.9,943.6C350.9,943.6 228.8,1031.7 186.1,1040.2L-8,1120.8V1385L1376,1379L1367,909C1361.5,929 1287.6,1027.2 1107,1027.2Z"
|
android:pathData="M819.5,856C638,856 518,772.5 359,772.5C200,772.5 100,860.5 65,869L-94,949.5V1041.5L1177.5,1025.5L1032.5,738C1028,758 967.4,856 819.5,856Z"
|
||||||
android:fillColor="#259CB4"/>
|
android:fillColor="#259CB4"/>
|
||||||
</group>
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_green_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_monochrome_shadow"/>
|
|
||||||
</adaptive-icon>
|
|
||||||
@@ -298,6 +298,9 @@
|
|||||||
<string name="preference_profiles_delete_alt">Delete</string>
|
<string name="preference_profiles_delete_alt">Delete</string>
|
||||||
<string name="preference_profiles_delete_undo_alt">Undo</string>
|
<string name="preference_profiles_delete_undo_alt">Undo</string>
|
||||||
|
|
||||||
|
<string name="preference_native_pacing">Native frame pacing</string>
|
||||||
|
<string name="preference_native_pacing_description">Reduces latency, but may worsen frame drops.</string>
|
||||||
|
|
||||||
<!-- ApplicationLogsActivity strings -->
|
<!-- ApplicationLogsActivity strings -->
|
||||||
<string name="title_activity_application_logs">Application logs</string>
|
<string name="title_activity_application_logs">Application logs</string>
|
||||||
<string name="application_logs_no_logs">No logs available.</string>
|
<string name="application_logs_no_logs">No logs available.</string>
|
||||||
@@ -338,7 +341,6 @@
|
|||||||
<string name="application_icon_pride">Pride</string>
|
<string name="application_icon_pride">Pride</string>
|
||||||
<string name="application_icon_trans">Transgender</string>
|
<string name="application_icon_trans">Transgender</string>
|
||||||
<string name="application_icon_sapphire">Sapphire</string>
|
<string name="application_icon_sapphire">Sapphire</string>
|
||||||
<string name="application_icon_green">Android</string>
|
|
||||||
<string name="application_icon_confirm">Change icon to %1$s?</string>
|
<string name="application_icon_confirm">Change icon to %1$s?</string>
|
||||||
<string name="application_icon_confirm_description">Geode Launcher will close itself to change the application icon.</string>
|
<string name="application_icon_confirm_description">Geode Launcher will close itself to change the application icon.</string>
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "9.4.1" apply false
|
id("com.android.application") version "9.4.0" apply false
|
||||||
id("com.android.library") version "9.4.1" apply false
|
id("com.android.library") version "9.4.0" apply false
|
||||||
id("org.jetbrains.kotlin.plugin.serialization") version "2.4.21" apply false
|
id("org.jetbrains.kotlin.plugin.serialization") version "2.4.10" apply false
|
||||||
id("org.jetbrains.kotlin.plugin.compose") version "2.4.21" apply false
|
id("org.jetbrains.kotlin.plugin.compose") version "2.4.10" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<Delete>("clean") {
|
tasks.register<Delete>("clean") {
|
||||||
|
|||||||
Reference in new issue
Block a user