diff options
Diffstat (limited to 'platform')
23 files changed, 391 insertions, 330 deletions
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index a663a847c2..2f6f483edf 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -862,6 +862,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String tname = string_table[name]; uint32_t attrcount = decode_uint32(&p_manifest[iofs + 20]); iofs += 28; + bool is_focus_aware_metadata = false; for (uint32_t i = 0; i < attrcount; i++) { uint32_t attr_nspace = decode_uint32(&p_manifest[iofs]); @@ -929,9 +930,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } } - if (tname == "meta-data" && attrname == "value" && value == "oculus_focus_aware_value") { + if (tname == "meta-data" && attrname == "value" && is_focus_aware_metadata) { // Update the focus awareness meta-data value - string_table.write[attr_value] = xr_mode_index == /* XRMode.OVR */ 1 && focus_awareness ? "true" : "false"; + encode_uint32(xr_mode_index == /* XRMode.OVR */ 1 && focus_awareness ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); } if (tname == "meta-data" && attrname == "value" && value == "plugins_value" && !plugins_names.empty()) { @@ -939,6 +940,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { string_table.write[attr_value] = plugins_names; } + is_focus_aware_metadata = tname == "meta-data" && attrname == "name" && value == "com.oculus.vr.focusaware"; iofs += 20; } diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml index dbf1dc0f3c..48c09552c1 100644 --- a/platform/android/java/app/AndroidManifest.xml +++ b/platform/android/java/app/AndroidManifest.xml @@ -45,8 +45,8 @@ android:resizeableActivity="false" tools:ignore="UnusedAttribute" > - <!-- Focus awareness metadata populated at export time if the user enables it in the 'Xr Features' section. --> - <meta-data android:name="com.oculus.vr.focusaware" android:value="oculus_focus_aware_value" /> + <!-- Focus awareness metadata is updated at export time if the user enables it in the 'Xr Features' section. --> + <meta-data android:name="com.oculus.vr.focusaware" android:value="false" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/platform/android/java/app/src/com/godot/game/GodotApp.java b/platform/android/java/app/src/com/godot/game/GodotApp.java index eb884404cd..1af5950cbe 100644 --- a/platform/android/java/app/src/com/godot/game/GodotApp.java +++ b/platform/android/java/app/src/com/godot/game/GodotApp.java @@ -30,11 +30,11 @@ package com.godot.game; -import org.godotengine.godot.Godot; +import org.godotengine.godot.FullScreenGodotApp; /** * Template activity for Godot Android custom builds. * Feel free to extend and modify this class for your custom logic. */ -public class GodotApp extends Godot { +public class GodotApp extends FullScreenGodotApp { } diff --git a/platform/android/java/lib/res/layout/godot_app_layout.xml b/platform/android/java/lib/res/layout/godot_app_layout.xml new file mode 100644 index 0000000000..386ded1c5d --- /dev/null +++ b/platform/android/java/lib/res/layout/godot_app_layout.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/godot_fragment_container" + android:layout_width="match_parent" + android:layout_height="match_parent" /> diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java new file mode 100644 index 0000000000..138c2de94c --- /dev/null +++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* FullScreenGodotApp.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +package org.godotengine.godot; + +import android.content.Intent; +import android.os.Bundle; +import android.view.KeyEvent; + +import androidx.fragment.app.FragmentActivity; + +/** + * Base activity for Android apps intending to use Godot as the primary and only screen. + * + * It's also a reference implementation for how to setup and use the {@link Godot} fragment + * within an Android app. + */ +public abstract class FullScreenGodotApp extends FragmentActivity { + protected Godot godotFragment; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.godot_app_layout); + godotFragment = new Godot(); + getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss(); + } + + @Override + public void onNewIntent(Intent intent) { + if (godotFragment != null) { + godotFragment.onNewIntent(intent); + } + } + + @Override + public void onBackPressed() { + if (godotFragment != null) { + godotFragment.onBackPressed(); + } else { + super.onBackPressed(); + } + } + + @Override + public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) { + if (godotFragment != null && godotFragment.onKeyMultiple(inKeyCode, repeatCount, event)) { + return true; + } + return super.onKeyMultiple(inKeyCode, repeatCount, event); + } +} diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index fcbbc86100..1b55090451 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -30,6 +30,9 @@ package org.godotengine.godot; +import static android.content.Context.MODE_PRIVATE; +import static android.content.Context.WINDOW_SERVICE; + import org.godotengine.godot.input.GodotEditText; import org.godotengine.godot.plugin.GodotPlugin; import org.godotengine.godot.plugin.GodotPluginRegistry; @@ -68,6 +71,7 @@ import android.os.Vibrator; import android.provider.Settings.Secure; import android.view.Display; import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -84,7 +88,7 @@ import android.widget.TextView; import androidx.annotation.CallSuper; import androidx.annotation.Keep; import androidx.annotation.NonNull; -import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.Fragment; import com.google.android.vending.expansion.downloader.DownloadProgressInfo; import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller; @@ -102,7 +106,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; -public abstract class Godot extends FragmentActivity implements SensorEventListener, IDownloaderClient { +public class Godot extends Fragment implements SensorEventListener, IDownloaderClient { private IStub mDownloaderClientStub; private TextView mStatusText; private TextView mProgressFraction; @@ -130,7 +134,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe static private Intent mCurrentIntent; - @Override public void onNewIntent(Intent intent) { mCurrentIntent = intent; } @@ -156,6 +159,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe private String[] command_line; private boolean use_apk_expansion; + private ViewGroup containerLayout; public GodotRenderView mRenderView; private boolean godot_initialized = false; @@ -174,7 +178,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe public ResultCallback result_callback; @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode, Intent data) { if (result_callback != null) { result_callback.callback(requestCode, resultCode, data); result_callback = null; @@ -211,27 +215,28 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe */ @Keep private void onVideoInit() { - final FrameLayout layout = new FrameLayout(this); - layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); - setContentView(layout); + final Activity activity = getActivity(); + containerLayout = new FrameLayout(activity); + containerLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); // GodotEditText layout - GodotEditText editText = new GodotEditText(this); + GodotEditText editText = new GodotEditText(activity); editText.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); // ...add to FrameLayout - layout.addView(editText); + containerLayout.addView(editText); GodotLib.setup(command_line); final String videoDriver = GodotLib.getGlobal("rendering/quality/driver/driver_name"); if (videoDriver.equals("Vulkan")) { - mRenderView = new GodotVulkanRenderView(this); + mRenderView = new GodotVulkanRenderView(activity, this); } else { - mRenderView = new GodotGLRenderView(this, xrMode, use_32_bits, use_debug_opengl); + mRenderView = new GodotGLRenderView(activity, this, xrMode, use_32_bits, + use_debug_opengl); } View view = mRenderView.getView(); - layout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + containerLayout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); editText.setView(mRenderView); io.setEdit(editText); @@ -239,7 +244,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe @Override public void onGlobalLayout() { Point fullSize = new Point(); - getWindowManager().getDefaultDisplay().getSize(fullSize); + activity.getWindowManager().getDefaultDisplay().getSize(fullSize); Rect gameSize = new Rect(); mRenderView.getView().getWindowVisibleDisplayFrame(gameSize); @@ -262,9 +267,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe // Include the returned non-null views in the Godot view hierarchy. for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { - View pluginView = plugin.onMainCreate(this); + View pluginView = plugin.onMainCreate(activity); if (pluginView != null) { - layout.addView(pluginView); + containerLayout.addView(pluginView); } } } @@ -274,9 +279,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe @Override public void run() { if (p_enabled) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } else { - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } } }); @@ -290,7 +295,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe @Keep private void vibrate(int durationMs) { if (requestPermission("VIBRATE")) { - Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE); + Vibrator v = (Vibrator)getContext().getSystemService(Context.VIBRATOR_SERVICE); if (v != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE)); @@ -314,13 +319,16 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe // Using instrumentation is a way of making the whole app process restart, because Android // will kill any process of the same package which was already running. // - Bundle args = new Bundle(); - args.putParcelable("intent", mCurrentIntent); - startInstrumentation(new ComponentName(this, GodotInstrumentation.class), null, args); + final Activity activity = getActivity(); + if (activity != null) { + Bundle args = new Bundle(); + args.putParcelable("intent", mCurrentIntent); + activity.startInstrumentation(new ComponentName(activity, GodotInstrumentation.class), null, args); + } } public void alert(final String message, final String title) { - final Activity activity = this; + final Activity activity = getActivity(); runOnUiThread(new Runnable() { @Override public void run() { @@ -340,7 +348,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } public int getGLESVersionCode() { - ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager am = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE); ConfigurationInfo deviceInfo = am.getDeviceConfigurationInfo(); return deviceInfo.reqGlEsVersion; } @@ -349,7 +357,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe protected String[] getCommandLine() { InputStream is; try { - is = getAssets().open("_cl_"); + is = getActivity().getAssets().open("_cl_"); byte[] len = new byte[4]; int r = is.read(len); if (r < 4) { @@ -426,11 +434,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe command_line = new_cmdline; } - io = new GodotIO(this); - io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); + final Activity activity = getActivity(); + io = new GodotIO(activity); + io.unique_id = Secure.getString(activity.getContentResolver(), Secure.ANDROID_ID); GodotLib.io = io; - netUtils = new GodotNetUtils(this); - mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); + netUtils = new GodotNetUtils(activity); + mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY); @@ -440,7 +449,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); - GodotLib.initialize(this, getAssets(), use_apk_expansion); + GodotLib.initialize(activity, this, activity.getAssets(), use_apk_expansion); result_callback = null; @@ -454,151 +463,152 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } @Override - protected void onCreate(Bundle icicle) { - super.onCreate(icicle); - Window window = getWindow(); + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) { + final Activity activity = getActivity(); + Window window = activity.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - mClipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE); + mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE); pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this); //check for apk expansion API - if (true) { - boolean md5mismatch = false; - command_line = getCommandLine(); - String main_pack_md5 = null; - String main_pack_key = null; - - List<String> new_args = new LinkedList<String>(); - - for (int i = 0; i < command_line.length; i++) { - boolean has_extra = i < command_line.length - 1; - if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) { - xrMode = XRMode.REGULAR; - } else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) { - xrMode = XRMode.OVR; - } else if (command_line[i].equals("--use_depth_32")) { - use_32_bits = true; - } else if (command_line[i].equals("--debug_opengl")) { - use_debug_opengl = true; - } else if (command_line[i].equals("--use_immersive")) { - use_immersive = true; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+ - window.getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar - View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - - UiChangeListener(); - } - } else if (command_line[i].equals("--use_apk_expansion")) { - use_apk_expansion = true; - } else if (has_extra && command_line[i].equals("--apk_expansion_md5")) { - main_pack_md5 = command_line[i + 1]; - i++; - } else if (has_extra && command_line[i].equals("--apk_expansion_key")) { - main_pack_key = command_line[i + 1]; - SharedPreferences prefs = getSharedPreferences("app_data_keys", MODE_PRIVATE); - Editor editor = prefs.edit(); - editor.putString("store_public_key", main_pack_key); - - editor.apply(); - i++; - } else if (command_line[i].trim().length() != 0) { - new_args.add(command_line[i]); + boolean md5mismatch = false; + command_line = getCommandLine(); + String main_pack_md5 = null; + String main_pack_key = null; + + List<String> new_args = new LinkedList<String>(); + + for (int i = 0; i < command_line.length; i++) { + boolean has_extra = i < command_line.length - 1; + if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) { + xrMode = XRMode.REGULAR; + } else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) { + xrMode = XRMode.OVR; + } else if (command_line[i].equals("--use_depth_32")) { + use_32_bits = true; + } else if (command_line[i].equals("--debug_opengl")) { + use_debug_opengl = true; + } else if (command_line[i].equals("--use_immersive")) { + use_immersive = true; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+ + window.getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar + View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + + UiChangeListener(); } + } else if (command_line[i].equals("--use_apk_expansion")) { + use_apk_expansion = true; + } else if (has_extra && command_line[i].equals("--apk_expansion_md5")) { + main_pack_md5 = command_line[i + 1]; + i++; + } else if (has_extra && command_line[i].equals("--apk_expansion_key")) { + main_pack_key = command_line[i + 1]; + SharedPreferences prefs = activity.getSharedPreferences("app_data_keys", + MODE_PRIVATE); + Editor editor = prefs.edit(); + editor.putString("store_public_key", main_pack_key); + + editor.apply(); + i++; + } else if (command_line[i].trim().length() != 0) { + new_args.add(command_line[i]); } + } - if (new_args.isEmpty()) { - command_line = null; - } else { - command_line = new_args.toArray(new String[new_args.size()]); + if (new_args.isEmpty()) { + command_line = null; + } else { + command_line = new_args.toArray(new String[new_args.size()]); + } + if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) { + //check that environment is ok! + if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + //show popup and die } - if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) { - //check that environment is ok! - if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - //show popup and die - } - // Build the full path to the app's expansion files - try { - expansion_pack_path = Helpers.getSaveFilePath(getApplicationContext()); - expansion_pack_path += "/main." + getPackageManager().getPackageInfo(getPackageName(), 0).versionCode + "." + this.getPackageName() + ".obb"; - } catch (Exception e) { - e.printStackTrace(); - } + // Build the full path to the app's expansion files + try { + expansion_pack_path = Helpers.getSaveFilePath(getContext()); + expansion_pack_path += "/main." + activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0).versionCode + "." + activity.getPackageName() + ".obb"; + } catch (Exception e) { + e.printStackTrace(); + } - File f = new File(expansion_pack_path); + File f = new File(expansion_pack_path); - boolean pack_valid = true; + boolean pack_valid = true; - if (!f.exists()) { - pack_valid = false; + if (!f.exists()) { + pack_valid = false; - } else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) { - pack_valid = false; - try { - f.delete(); - } catch (Exception e) { - } + } else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) { + pack_valid = false; + try { + f.delete(); + } catch (Exception e) { } + } - if (!pack_valid) { - Intent notifierIntent = new Intent(this, this.getClass()); - notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - Intent.FLAG_ACTIVITY_CLEAR_TOP); + if (!pack_valid) { + Intent notifierIntent = new Intent(activity, activity.getClass()); + notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_ACTIVITY_CLEAR_TOP); - PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, - notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0, + notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); - int startResult; - try { - startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( - getApplicationContext(), - pendingIntent, + int startResult; + try { + startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( + getContext(), + pendingIntent, + GodotDownloaderService.class); + + if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { + // This is where you do set up to display the download + // progress (next step) + mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this, GodotDownloaderService.class); - if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { - // This is where you do set up to display the download - // progress (next step) - mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this, - GodotDownloaderService.class); - - setContentView(R.layout.downloading_expansion); - mPB = (ProgressBar)findViewById(R.id.progressBar); - mStatusText = (TextView)findViewById(R.id.statusText); - mProgressFraction = (TextView)findViewById(R.id.progressAsFraction); - mProgressPercent = (TextView)findViewById(R.id.progressAsPercentage); - mAverageSpeed = (TextView)findViewById(R.id.progressAverageSpeed); - mTimeRemaining = (TextView)findViewById(R.id.progressTimeRemaining); - mDashboard = findViewById(R.id.downloaderDashboard); - mCellMessage = findViewById(R.id.approveCellular); - mPauseButton = (Button)findViewById(R.id.pauseButton); - mWiFiSettingsButton = (Button)findViewById(R.id.wifiSettingsButton); - - return; - } - } catch (NameNotFoundException e) { - // TODO Auto-generated catch block + View downloadingExpansionView = + inflater.inflate(R.layout.downloading_expansion, container, false); + mPB = (ProgressBar)downloadingExpansionView.findViewById(R.id.progressBar); + mStatusText = (TextView)downloadingExpansionView.findViewById(R.id.statusText); + mProgressFraction = (TextView)downloadingExpansionView.findViewById(R.id.progressAsFraction); + mProgressPercent = (TextView)downloadingExpansionView.findViewById(R.id.progressAsPercentage); + mAverageSpeed = (TextView)downloadingExpansionView.findViewById(R.id.progressAverageSpeed); + mTimeRemaining = (TextView)downloadingExpansionView.findViewById(R.id.progressTimeRemaining); + mDashboard = downloadingExpansionView.findViewById(R.id.downloaderDashboard); + mCellMessage = downloadingExpansionView.findViewById(R.id.approveCellular); + mPauseButton = (Button)downloadingExpansionView.findViewById(R.id.pauseButton); + mWiFiSettingsButton = (Button)downloadingExpansionView.findViewById(R.id.wifiSettingsButton); + + return downloadingExpansionView; } + } catch (NameNotFoundException e) { + // TODO Auto-generated catch block } } } - mCurrentIntent = getIntent(); + mCurrentIntent = activity.getIntent(); initializeGodot(); + return containerLayout; } @Override - protected void onDestroy() { + public void onDestroy() { for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { plugin.onMainDestroy(); } - GodotLib.ondestroy(this); + GodotLib.ondestroy(); super.onDestroy(); @@ -608,13 +618,13 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } @Override - protected void onPause() { + public void onPause() { super.onPause(); activityResumed = false; if (!godot_initialized) { if (null != mDownloaderClientStub) { - mDownloaderClientStub.disconnect(this); + mDownloaderClientStub.disconnect(getActivity()); } return; } @@ -644,12 +654,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } @Override - protected void onResume() { + public void onResume() { super.onResume(); activityResumed = true; if (!godot_initialized) { if (null != mDownloaderClientStub) { - mDownloaderClientStub.connect(this); + mDownloaderClientStub.connect(getActivity()); } return; } @@ -662,7 +672,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); if (use_immersive && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+ - Window window = getWindow(); + Window window = getActivity().getWindow(); window.getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | @@ -678,7 +688,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } public void UiChangeListener() { - final View decorView = getWindow().getDecorView(); + final View decorView = getActivity().getWindow().getDecorView(); decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { @@ -699,7 +709,8 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe @Override public void onSensorChanged(SensorEvent event) { - Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); + Display display = + ((WindowManager)getActivity().getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); int displayRotation = display.getRotation(); float[] adjustedValues = new float[3]; @@ -762,7 +773,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } */ - @Override public void onBackPressed() { boolean shouldQuit = true; @@ -793,6 +803,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } } + public final void runOnUiThread(@NonNull Runnable action) { + if (getActivity() != null) { + getActivity().runOnUiThread(action); + } + } + private void forceQuit() { System.exit(0); } @@ -895,18 +911,17 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe return true; } - @Override public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) { String s = event.getCharacters(); if (s == null || s.length() == 0) - return super.onKeyMultiple(inKeyCode, repeatCount, event); + return false; final char[] cc = s.toCharArray(); int cnt = 0; for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0) ; if (cnt == 0) - return super.onKeyMultiple(inKeyCode, repeatCount, event); + return false; mRenderView.queueOnRenderThread(new Runnable() { // This method will be called on the rendering thread: public void run() { @@ -924,15 +939,15 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } public boolean requestPermission(String p_name) { - return PermissionsUtil.requestPermission(p_name, this); + return PermissionsUtil.requestPermission(p_name, getActivity()); } public boolean requestPermissions() { - return PermissionsUtil.requestManifestPermissions(this); + return PermissionsUtil.requestManifestPermissions(getActivity()); } public String[] getGrantedPermissions() { - return PermissionsUtil.getGrantedPermissions(this); + return PermissionsUtil.getGrantedPermissions(getActivity()); } /** diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index 14dd893faa..4da2f31250 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -42,6 +42,7 @@ import org.godotengine.godot.xr.regular.RegularContextFactory; import org.godotengine.godot.xr.regular.RegularFallbackConfigChooser; import android.annotation.SuppressLint; +import android.content.Context; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; import android.view.GestureDetector; @@ -68,19 +69,20 @@ import android.view.SurfaceView; * bit depths). Failure to do so would result in an EGL_BAD_MATCH error. */ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView { - private final Godot activity; + private final Godot godot; private final GodotInputHandler inputHandler; private final GestureDetector detector; private final GodotRenderer godotRenderer; - public GodotGLRenderView(Godot activity, XRMode xrMode, boolean p_use_32_bits, boolean p_use_debug_opengl) { - super(activity); + public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_32_bits, + boolean p_use_debug_opengl) { + super(context); GLUtils.use_32 = p_use_32_bits; GLUtils.use_debug_opengl = p_use_debug_opengl; - this.activity = activity; + this.godot = godot; this.inputHandler = new GodotInputHandler(this); - this.detector = new GestureDetector(activity, new GodotGestureHandler(this)); + this.detector = new GestureDetector(context, new GodotGestureHandler(this)); this.godotRenderer = new GodotRenderer(); init(xrMode, false, 16, 0); } @@ -112,7 +114,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView @Override public void onBackPressed() { - activity.onBackPressed(); + godot.onBackPressed(); } @SuppressLint("ClickableViewAccessibility") @@ -120,7 +122,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); this.detector.onTouchEvent(event); - return activity.gotTouchEvent(event); + return godot.gotTouchEvent(event); } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index 93f4786e83..4dd228e53b 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -32,6 +32,7 @@ package org.godotengine.godot; import org.godotengine.godot.input.*; +import android.app.Activity; import android.content.*; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -51,7 +52,7 @@ import java.util.Locale; public class GodotIO { AssetManager am; - Godot activity; + final Activity activity; GodotEditText edit; final int SCREEN_LANDSCAPE = 0; @@ -314,7 +315,7 @@ public class GodotIO { dirs.remove(id); } - GodotIO(Godot p_activity) { + GodotIO(Activity p_activity) { am = p_activity.getAssets(); activity = p_activity; //streams = new HashMap<Integer, AssetData>(); diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index 3693f36557..318e2816ff 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -50,13 +50,13 @@ public class GodotLib { /** * Invoked on the main thread to initialize Godot native layer. */ - public static native void initialize(Godot p_instance, Object p_asset_manager, boolean use_apk_expansion); + public static native void initialize(Activity activity, Godot p_instance, Object p_asset_manager, boolean use_apk_expansion); /** * Invoked on the main thread to clean up Godot native layer. - * @see Activity#onDestroy() + * @see androidx.fragment.app.Fragment#onDestroy() */ - public static native void ondestroy(Godot p_instance); + public static native void ondestroy(); /** * Invoked on the GL thread to complete setup for the Godot native layer logic. @@ -161,14 +161,14 @@ public class GodotLib { public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name); /** - * Invoked when the Android activity resumes. - * @see Activity#onResume() + * Invoked when the Android app resumes. + * @see androidx.fragment.app.Fragment#onResume() */ public static native void focusin(); /** - * Invoked when the Android activity pauses. - * @see Activity#onPause() + * Invoked when the Android app pauses. + * @see androidx.fragment.app.Fragment#onPause() */ public static native void focusout(); diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java index e9872b58ff..aace593bae 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java @@ -36,23 +36,24 @@ import org.godotengine.godot.vulkan.VkRenderer; import org.godotengine.godot.vulkan.VkSurfaceView; import android.annotation.SuppressLint; +import android.content.Context; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.SurfaceView; public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView { - private final Godot mActivity; + private final Godot godot; private final GodotInputHandler mInputHandler; private final GestureDetector mGestureDetector; private final VkRenderer mRenderer; - public GodotVulkanRenderView(Godot activity) { - super(activity); + public GodotVulkanRenderView(Context context, Godot godot) { + super(context); - mActivity = activity; + this.godot = godot; mInputHandler = new GodotInputHandler(this); - mGestureDetector = new GestureDetector(mActivity, new GodotGestureHandler(this)); + mGestureDetector = new GestureDetector(context, new GodotGestureHandler(this)); mRenderer = new VkRenderer(); setFocusableInTouchMode(true); @@ -86,7 +87,7 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV @Override public void onBackPressed() { - mActivity.onBackPressed(); + godot.onBackPressed(); } @SuppressLint("ClickableViewAccessibility") @@ -94,7 +95,7 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); mGestureDetector.onTouchEvent(event); - return mActivity.gotTouchEvent(event); + return godot.gotTouchEvent(event); } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java index ce85880fa3..93c204935c 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java @@ -98,7 +98,7 @@ public abstract class GodotPlugin { */ @Nullable protected Activity getActivity() { - return godot; + return godot.getActivity(); } /** diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java index 12d2ed09fb..1c2d1a6563 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java @@ -32,6 +32,7 @@ package org.godotengine.godot.plugin; import org.godotengine.godot.Godot; +import android.app.Activity; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Bundle; @@ -121,9 +122,11 @@ public final class GodotPluginRegistry { private void loadPlugins(Godot godot) { try { - ApplicationInfo appInfo = godot + final Activity activity = godot.getActivity(); + ApplicationInfo appInfo = activity .getPackageManager() - .getApplicationInfo(godot.getPackageName(), PackageManager.GET_META_DATA); + .getApplicationInfo(activity.getPackageName(), + PackageManager.GET_META_DATA); Bundle metaData = appInfo.metaData; if (metaData == null || metaData.isEmpty()) { return; diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java b/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java index 0832a9b965..c89118ad55 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java @@ -30,8 +30,7 @@ package org.godotengine.godot.utils; -import org.godotengine.godot.Godot; - +import android.app.Activity; import android.content.Context; import android.net.wifi.WifiManager; import android.util.Log; @@ -45,7 +44,7 @@ public class GodotNetUtils { /* A single, reference counted, multicast lock, or null if permission CHANGE_WIFI_MULTICAST_STATE is missing */ private WifiManager.MulticastLock multicastLock; - public GodotNetUtils(Godot p_activity) { + public GodotNetUtils(Activity p_activity) { if (PermissionsUtil.hasManifestPermission(p_activity, "android.permission.CHANGE_WIFI_MULTICAST_STATE")) { WifiManager wifi = (WifiManager)p_activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE); multicastLock = wifi.createMulticastLock("GodotMulticastLock"); diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java index 6837e4f147..7104baf86e 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java @@ -30,9 +30,8 @@ package org.godotengine.godot.utils; -import org.godotengine.godot.Godot; - import android.Manifest; +import android.app.Activity; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; @@ -65,7 +64,7 @@ public final class PermissionsUtil { * @param activity the caller activity for this method. * @return true/false. "true" if permission was granted otherwise returns "false". */ - public static boolean requestPermission(String name, Godot activity) { + public static boolean requestPermission(String name, Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { // Not necessary, asked on install already return true; @@ -93,7 +92,7 @@ public final class PermissionsUtil { * @param activity the caller activity for this method. * @return true/false. "true" if all permissions were granted otherwise returns "false". */ - public static boolean requestManifestPermissions(Godot activity) { + public static boolean requestManifestPermissions(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } @@ -138,7 +137,7 @@ public final class PermissionsUtil { * @param activity the caller activity for this method. * @return granted permissions list */ - public static String[] getGrantedPermissions(Godot activity) { + public static String[] getGrantedPermissions(Activity activity) { String[] manifestPermissions; try { manifestPermissions = getManifestPermissions(activity); @@ -172,7 +171,7 @@ public final class PermissionsUtil { * @param permission the permession to look for in the manifest file. * @return "true" if the permission is in the manifest file of the activity, "false" otherwise. */ - public static boolean hasManifestPermission(Godot activity, String permission) { + public static boolean hasManifestPermission(Activity activity, String permission) { try { for (String p : getManifestPermissions(activity)) { if (permission.equals(p)) @@ -190,7 +189,7 @@ public final class PermissionsUtil { * @return manifest permissions list * @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found. */ - private static String[] getManifestPermissions(Godot activity) throws PackageManager.NameNotFoundException { + private static String[] getManifestPermissions(Activity activity) throws PackageManager.NameNotFoundException { PackageManager packageManager = activity.getPackageManager(); PackageInfo packageInfo = packageManager.getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS); if (packageInfo.requestedPermissions == null) @@ -205,7 +204,7 @@ public final class PermissionsUtil { * @return permission info object * @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found. */ - private static PermissionInfo getPermissionInfo(Godot activity, String permission) throws PackageManager.NameNotFoundException { + private static PermissionInfo getPermissionInfo(Activity activity, String permission) throws PackageManager.NameNotFoundException { PackageManager packageManager = activity.getPackageManager(); return packageManager.getPermissionInfo(permission, 0); } diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index 39de3cb642..9b44ac4b41 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -1150,7 +1150,7 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) { JNIEnv *env = ThreadAndroid::get_env(); - jclass activityClass = env->FindClass("org/godotengine/godot/Godot"); + jclass activityClass = env->FindClass("android/app/Activity"); jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); classLoader = env->CallObjectMethod(p_activity, getClassLoader); classLoader = (jclass)env->NewGlobalRef(classLoader); diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 8667727b1d..a032ae8d2c 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -77,14 +77,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei } } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion) { initialized = true; JavaVM *jvm; env->GetJavaVM(&jvm); // create our wrapper classes - godot_java = new GodotJavaWrapper(env, activity); // our activity is our godot instance is our activity.. + godot_java = new GodotJavaWrapper(env, activity, godot_instance); godot_io_java = new GodotIOJavaWrapper(env, godot_java->get_member_object("io", "Lorg/godotengine/godot/GodotIO;", env)); ThreadAndroid::make_default(jvm); @@ -109,7 +109,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en godot_java->on_video_init(env); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz) { // lets cleanup if (godot_io_java) { delete godot_io_java; diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index e8be7be0d0..07584518e5 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -37,8 +37,8 @@ // These functions can be called from within JAVA and are the means by which our JAVA implementation calls back into our C++ code. // See java/src/org/godotengine/godot/GodotLib.java for the JAVA side of this (yes that's why we have the long names) extern "C" { -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jobject p_surface, jint p_width, jint p_height); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jobject p_surface, jboolean p_32_bits); diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index 8ef99dfab0..cff591d903 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -37,36 +37,47 @@ // TODO we could probably create a base class for this... -GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance) { +GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance) { godot_instance = p_env->NewGlobalRef(p_godot_instance); + activity = p_env->NewGlobalRef(p_activity); // get info about our Godot class so we can get pointers and stuff... - cls = p_env->FindClass("org/godotengine/godot/Godot"); - if (cls) { - cls = (jclass)p_env->NewGlobalRef(cls); + godot_class = p_env->FindClass("org/godotengine/godot/Godot"); + if (godot_class) { + godot_class = (jclass)p_env->NewGlobalRef(godot_class); + } else { + // this is a pretty serious fail.. bail... pointers will stay 0 + return; + } + activity_class = p_env->FindClass("android/app/Activity"); + if (activity_class) { + activity_class = (jclass)p_env->NewGlobalRef(activity_class); } else { // this is a pretty serious fail.. bail... pointers will stay 0 return; } - // get some method pointers... - _on_video_init = p_env->GetMethodID(cls, "onVideoInit", "()V"); - _restart = p_env->GetMethodID(cls, "restart", "()V"); - _finish = p_env->GetMethodID(cls, "forceQuit", "()V"); - _set_keep_screen_on = p_env->GetMethodID(cls, "setKeepScreenOn", "(Z)V"); - _alert = p_env->GetMethodID(cls, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); - _get_GLES_version_code = p_env->GetMethodID(cls, "getGLESVersionCode", "()I"); - _get_clipboard = p_env->GetMethodID(cls, "getClipboard", "()Ljava/lang/String;"); - _set_clipboard = p_env->GetMethodID(cls, "setClipboard", "(Ljava/lang/String;)V"); - _request_permission = p_env->GetMethodID(cls, "requestPermission", "(Ljava/lang/String;)Z"); - _request_permissions = p_env->GetMethodID(cls, "requestPermissions", "()Z"); - _get_granted_permissions = p_env->GetMethodID(cls, "getGrantedPermissions", "()[Ljava/lang/String;"); - _init_input_devices = p_env->GetMethodID(cls, "initInputDevices", "()V"); - _get_surface = p_env->GetMethodID(cls, "getSurface", "()Landroid/view/Surface;"); - _is_activity_resumed = p_env->GetMethodID(cls, "isActivityResumed", "()Z"); - _vibrate = p_env->GetMethodID(cls, "vibrate", "(I)V"); - _get_input_fallback_mapping = p_env->GetMethodID(cls, "getInputFallbackMapping", "()Ljava/lang/String;"); - _on_godot_main_loop_started = p_env->GetMethodID(cls, "onGodotMainLoopStarted", "()V"); + // get some Godot method pointers... + _on_video_init = p_env->GetMethodID(godot_class, "onVideoInit", "()V"); + _restart = p_env->GetMethodID(godot_class, "restart", "()V"); + _finish = p_env->GetMethodID(godot_class, "forceQuit", "()V"); + _set_keep_screen_on = p_env->GetMethodID(godot_class, "setKeepScreenOn", "(Z)V"); + _alert = p_env->GetMethodID(godot_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); + _get_GLES_version_code = p_env->GetMethodID(godot_class, "getGLESVersionCode", "()I"); + _get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;"); + _set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V"); + _request_permission = p_env->GetMethodID(godot_class, "requestPermission", "(Ljava/lang/String;)Z"); + _request_permissions = p_env->GetMethodID(godot_class, "requestPermissions", "()Z"); + _get_granted_permissions = p_env->GetMethodID(godot_class, "getGrantedPermissions", "()[Ljava/lang/String;"); + _init_input_devices = p_env->GetMethodID(godot_class, "initInputDevices", "()V"); + _get_surface = p_env->GetMethodID(godot_class, "getSurface", "()Landroid/view/Surface;"); + _is_activity_resumed = p_env->GetMethodID(godot_class, "isActivityResumed", "()Z"); + _vibrate = p_env->GetMethodID(godot_class, "vibrate", "(I)V"); + _get_input_fallback_mapping = p_env->GetMethodID(godot_class, "getInputFallbackMapping", "()Ljava/lang/String;"); + _on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V"); + + // get some Activity method pointers... + _get_class_loader = p_env->GetMethodID(activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;"); } GodotJavaWrapper::~GodotJavaWrapper() { @@ -74,27 +85,25 @@ GodotJavaWrapper::~GodotJavaWrapper() { } jobject GodotJavaWrapper::get_activity() { - // our godot instance is our activity - return godot_instance; + return activity; } jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_class, JNIEnv *p_env) { - if (cls) { + if (godot_class) { if (p_env == nullptr) p_env = ThreadAndroid::get_env(); - jfieldID fid = p_env->GetStaticFieldID(cls, p_name, p_class); - return p_env->GetStaticObjectField(cls, fid); + jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class); + return p_env->GetStaticObjectField(godot_class, fid); } else { return nullptr; } } jobject GodotJavaWrapper::get_class_loader() { - if (cls) { + if (_get_class_loader) { JNIEnv *env = ThreadAndroid::get_env(); - jmethodID getClassLoader = env->GetMethodID(cls, "getClassLoader", "()Ljava/lang/ClassLoader;"); - return env->CallObjectMethod(godot_instance, getClassLoader); + return env->CallObjectMethod(godot_instance, _get_class_loader); } else { return nullptr; } diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index 89d6b6db46..e0c3809a64 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -43,7 +43,9 @@ class GodotJavaWrapper { private: jobject godot_instance; - jclass cls; + jobject activity; + jclass godot_class; + jclass activity_class; jmethodID _on_video_init = 0; jmethodID _restart = 0; @@ -62,9 +64,10 @@ private: jmethodID _vibrate = 0; jmethodID _get_input_fallback_mapping = 0; jmethodID _on_godot_main_loop_started = 0; + jmethodID _get_class_loader = 0; public: - GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance); + GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance); ~GodotJavaWrapper(); jobject get_activity(); diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index a0954600a2..94c2e989f1 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -32,12 +32,12 @@ #ifdef X11_ENABLED -#include "detect_prime_x11.h" - -#include "core/os/dir_access.h" #include "core/print_string.h" -#include "errno.h" +#include "core/project_settings.h" +#include "detect_prime_x11.h" #include "key_mapping_x11.h" +#include "main/main.h" +#include "scene/resources/texture.h" #if defined(OPENGL_ENABLED) #include "drivers/gles2/rasterizer_gles2.h" @@ -47,20 +47,14 @@ #include "servers/rendering/rasterizer_rd/rasterizer_rd.h" #endif -#include "scene/resources/texture.h" - -#ifdef HAVE_MNTENT -#include <mntent.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "X11/Xutil.h" +#include <X11/Xatom.h> +#include <X11/Xutil.h> +#include <X11/extensions/Xinerama.h> -#include "X11/Xatom.h" -#include "X11/extensions/Xinerama.h" // ICCCM #define WM_NormalState 1L // window normal state #define WM_IconicState 3L // window minimized @@ -69,8 +63,6 @@ #define _NET_WM_STATE_ADD 1L // add/set property #define _NET_WM_STATE_TOGGLE 2L // toggle property -#include "main/main.h" - #include <dlfcn.h> #include <fcntl.h> #include <sys/stat.h> @@ -82,14 +74,9 @@ #undef KEY_TAB #endif -#include <X11/Xatom.h> - #undef CursorShape - #include <X11/XKBlib.h> -#include "core/project_settings.h" - // 2.2 is the first release with multitouch #define XINPUT_CLIENT_VERSION_MAJOR 2 #define XINPUT_CLIENT_VERSION_MINOR 2 @@ -417,10 +404,6 @@ void DisplayServerX11::mouse_warp_to_position(const Point2i &p_to) { if (mouse_mode == MOUSE_MODE_CAPTURED) { last_mouse_pos = p_to; } else { - /*XWindowAttributes xwa; - XGetWindowAttributes(x11_display, x11_window, &xwa); - printf("%d %d\n", xwa.x, xwa.y); needed? */ - XWarpPointer(x11_display, None, windows[MAIN_WINDOW_ID].x11_window, 0, 0, 0, 0, (int)p_to.x, (int)p_to.y); } @@ -1098,18 +1081,19 @@ Size2i DisplayServerX11::window_get_real_size(WindowID p_window) const { return Size2i(w, h); } -bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const { - _THREAD_SAFE_METHOD_ - +// Just a helper to reduce code duplication in `window_is_maximize_allowed` +// and `_set_wm_maximized`. +bool DisplayServerX11::_window_maximize_check(WindowID p_window, const char *p_atom_name) const { ERR_FAIL_COND_V(!windows.has(p_window), false); const WindowData &wd = windows[p_window]; - Atom property = XInternAtom(x11_display, "_NET_WM_ALLOWED_ACTIONS", False); + Atom property = XInternAtom(x11_display, p_atom_name, False); Atom type; int format; unsigned long len; unsigned long remaining; unsigned char *data = nullptr; + bool retval = false; int result = XGetWindowProperty( x11_display, @@ -1141,13 +1125,20 @@ bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const { } if (found_wm_act_max_horz || found_wm_act_max_vert) { - return true; + retval = true; + break; } } - XFree(atoms); + + XFree(data); } - return false; + return retval; +} + +bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + return _window_maximize_check(p_window, "_NET_WM_ALLOWED_ACTIONS"); } void DisplayServerX11::_set_wm_maximized(WindowID p_window, bool p_enabled) { @@ -1385,60 +1376,14 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c if (wd.fullscreen) { //if fullscreen, it's not in another mode return WINDOW_MODE_FULLSCREEN; } - { //test maximized - // Using EWMH -- Extended Window Manager Hints - Atom property = XInternAtom(x11_display, "_NET_WM_STATE", False); - Atom type; - int format; - unsigned long len; - unsigned long remaining; - unsigned char *data = nullptr; - bool retval = false; - int result = XGetWindowProperty( - x11_display, - wd.x11_window, - property, - 0, - 1024, - False, - XA_ATOM, - &type, - &format, - &len, - &remaining, - &data); - - if (result == Success && data) { - Atom *atoms = (Atom *)data; - Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); - bool found_wm_max_horz = false; - bool found_wm_max_vert = false; - - for (uint64_t i = 0; i < len; i++) { - if (atoms[i] == wm_max_horz) { - found_wm_max_horz = true; - } - if (atoms[i] == wm_max_vert) { - found_wm_max_vert = true; - } - - if (found_wm_max_horz && found_wm_max_vert) { - retval = true; - break; - } - } - - XFree(data); - } - - if (retval) { - return WINDOW_MODE_MAXIMIZED; - } + // Test maximized. + // Using EWMH -- Extended Window Manager Hints + if (_window_maximize_check(p_window, "_NET_WM_STATE")) { + return WINDOW_MODE_MAXIMIZED; } - { // test minimzed + { // Test minimized. // Using ICCCM -- Inter-Client Communication Conventions Manual Atom property = XInternAtom(x11_display, "WM_STATE", True); Atom type; @@ -1471,7 +1416,7 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c } } - // all other discarded, return windowed. + // All other discarded, return windowed. return WINDOW_MODE_WINDOWED; } diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index f01b9a2323..3b2ff0e08d 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -36,7 +36,6 @@ #include "servers/display_server.h" #include "core/input/input.h" - #include "drivers/alsa/audio_driver_alsa.h" #include "drivers/alsamidi/midi_driver_alsamidi.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" @@ -231,6 +230,7 @@ class DisplayServerX11 : public DisplayServer { static Property _read_property(Display *p_display, Window p_window, Atom p_property); void _update_real_mouse_position(const WindowData &wd); + bool _window_maximize_check(WindowID p_window, const char *p_atom_name) const; void _set_wm_fullscreen(WindowID p_window, bool p_enabled); void _set_wm_maximized(WindowID p_window, bool p_enabled); diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 09a5eca914..8c6f3b1167 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -31,8 +31,11 @@ #include "os_linuxbsd.h" #include "core/os/dir_access.h" -#include "core/print_string.h" -#include "errno.h" +#include "main/main.h" + +#ifdef X11_ENABLED +#include "display_server_x11.h" +#endif #ifdef HAVE_MNTENT #include <mntent.h> @@ -48,12 +51,6 @@ #include <sys/types.h> #include <unistd.h> -#include "main/main.h" - -#ifdef X11_ENABLED -#include "display_server_x11.h" -#endif - void OS_LinuxBSD::initialize() { crash_handler.initialize(); diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 9af7c02351..916816325d 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -825,14 +825,15 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String zipfi.tmz_date.tm_hour = time.hour; zipfi.tmz_date.tm_mday = date.day; zipfi.tmz_date.tm_min = time.min; - zipfi.tmz_date.tm_mon = date.month; + zipfi.tmz_date.tm_mon = date.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, http://www.cplusplus.com/reference/ctime/tm/ zipfi.tmz_date.tm_sec = time.sec; zipfi.tmz_date.tm_year = date.year; zipfi.dosDate = 0; // 0100000: regular file type // 0000755: permissions rwxr-xr-x // 0000644: permissions rw-r--r-- - zipfi.external_fa = (is_executable ? 0100755 : 0100644) << 16L; + uint32_t _mode = (is_executable ? 0100755 : 0100644); + zipfi.external_fa = (_mode << 16L) | !(_mode & 0200); zipfi.internal_fa = 0; zipOpenNewFileInZip4(p_zip, |