diff --git a/README.md b/README.md index bd9839bc5..990448364 100644 --- a/README.md +++ b/README.md @@ -108,3 +108,4 @@ Any code change should be submitted as a pull request. The description should ex - [xHook](https://github.com/iqiyi/xHook) (Used for exit code trapping): [MIT and BSD-style licenses](https://github.com/iqiyi/xHook/blob/master/LICENSE). - [libepoxy](https://github.com/anholt/libepoxy): [MIT License](https://github.com/anholt/libepoxy/blob/master/COPYING). - [virglrenderer](https://github.com/PojavLauncherTeam/virglrenderer): [MIT License](https://gitlab.freedesktop.org/virgl/virglrenderer/-/blob/master/COPYING). +- Thanks to [MCHeads](https://mc-heads.net) for providing Minecraft avatars. diff --git a/app_pojavlauncher/src/main/AndroidManifest.xml b/app_pojavlauncher/src/main/AndroidManifest.xml index d8fe8db22..28c2ea9e0 100644 --- a/app_pojavlauncher/src/main/AndroidManifest.xml +++ b/app_pojavlauncher/src/main/AndroidManifest.xml @@ -59,12 +59,12 @@ diff --git a/app_pojavlauncher/src/main/assets/components/lwjgl3/version b/app_pojavlauncher/src/main/assets/components/lwjgl3/version index 4dc8ff272..bdd22c5d4 100644 --- a/app_pojavlauncher/src/main/assets/components/lwjgl3/version +++ b/app_pojavlauncher/src/main/assets/components/lwjgl3/version @@ -1 +1 @@ -20211115 +20220304 diff --git a/app_pojavlauncher/src/main/java/com/kdt/DefocusableScrollView.java b/app_pojavlauncher/src/main/java/com/kdt/DefocusableScrollView.java index 9bbde79b4..049a46b98 100644 --- a/app_pojavlauncher/src/main/java/com/kdt/DefocusableScrollView.java +++ b/app_pojavlauncher/src/main/java/com/kdt/DefocusableScrollView.java @@ -5,15 +5,15 @@ import android.graphics.Rect; import android.util.AttributeSet; import android.widget.ScrollView; +/** + Class allowing to ignore the focusing from an item such an EditText within it. + Ignoring it will stop the scrollView from refocusing on the view +*/ public class DefocusableScrollView extends ScrollView { - /* - What is this class for ? - It allows to ignore the focusing from an item such an EditText. - Ignoring it will stop the scrollView from refocusing on the view - */ - private boolean keepFocusing = false; + + private boolean mKeepFocusing = false; public DefocusableScrollView(Context context) { @@ -33,16 +33,16 @@ public class DefocusableScrollView extends ScrollView { } public void setKeepFocusing(boolean shouldKeepFocusing){ - keepFocusing = shouldKeepFocusing; + mKeepFocusing = shouldKeepFocusing; } public boolean isKeepFocusing(){ - return keepFocusing; + return mKeepFocusing; } @Override protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) { - if(!keepFocusing) return 0; + if(!mKeepFocusing) return 0; return super.computeScrollDeltaToGetChildRectOnScreen(rect); } diff --git a/app_pojavlauncher/src/main/java/com/kdt/LoggerView.java b/app_pojavlauncher/src/main/java/com/kdt/LoggerView.java index 7df8a4ad0..b77ffeb68 100644 --- a/app_pojavlauncher/src/main/java/com/kdt/LoggerView.java +++ b/app_pojavlauncher/src/main/java/com/kdt/LoggerView.java @@ -21,10 +21,10 @@ import net.kdt.pojavlaunch.R; * It has support for the Logger class */ public class LoggerView extends ConstraintLayout { - private Logger.eventLogListener logListener; - private ToggleButton toggleButton; - private ScrollView scrollView; - private TextView log; + private Logger.eventLogListener mLogListener; + private ToggleButton mToggleButton; + private ScrollView mScrollView; + private TextView mLogTextView; public LoggerView(@NonNull Context context) { @@ -36,50 +36,51 @@ public class LoggerView extends ConstraintLayout { init(); } + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + // Triggers the log view shown state by default when viewing it + mToggleButton.setChecked(visibility == VISIBLE); + } + /** * Inflate the layout, and add component behaviors */ private void init(){ - inflate(getContext(), R.layout.loggerview_layout, this); - log = findViewById(R.id.content_log_view); - log.setTypeface(Typeface.MONOSPACE); + inflate(getContext(), R.layout.view_logger, this); + mLogTextView = findViewById(R.id.content_log_view); + mLogTextView.setTypeface(Typeface.MONOSPACE); //TODO clamp the max text so it doesn't go oob - log.setMaxLines(Integer.MAX_VALUE); - log.setEllipsize(null); - log.setVisibility(GONE); + mLogTextView.setMaxLines(Integer.MAX_VALUE); + mLogTextView.setEllipsize(null); + mLogTextView.setVisibility(GONE); // Toggle log visibility - toggleButton = findViewById(R.id.content_log_toggle_log); - toggleButton.setOnCheckedChangeListener( + mToggleButton = findViewById(R.id.content_log_toggle_log); + mToggleButton.setOnCheckedChangeListener( (compoundButton, isChecked) -> { - log.setVisibility(isChecked ? VISIBLE : GONE); - if(!isChecked) log.setText(""); + mLogTextView.setVisibility(isChecked ? VISIBLE : GONE); + if(!isChecked) mLogTextView.setText(""); }); - toggleButton.setChecked(false); + mToggleButton.setChecked(false); // Remove the loggerView from the user View ImageButton cancelButton = findViewById(R.id.log_view_cancel); cancelButton.setOnClickListener(view -> LoggerView.this.setVisibility(GONE)); // Set the scroll view - scrollView = findViewById(R.id.content_log_scroll); + mScrollView = findViewById(R.id.content_log_scroll); // Listen to logs - logListener = text -> { - if(log.getVisibility() != VISIBLE) return; + mLogListener = text -> { + if(mLogTextView.getVisibility() != VISIBLE) return; post(() -> { - log.append(text + '\n'); - scrollView.fullScroll(View.FOCUS_DOWN); + mLogTextView.append(text + '\n'); + mScrollView.fullScroll(View.FOCUS_DOWN); }); }; - Logger.getInstance().setLogListener(logListener); + Logger.getInstance().setLogListener(mLogListener); } - @Override - public void setVisibility(int visibility) { - super.setVisibility(visibility); - // Triggers the log view shown state by default when viewing it - toggleButton.setChecked(visibility == VISIBLE); - } } diff --git a/app_pojavlauncher/src/main/java/com/kdt/mcgui/MineButton.java b/app_pojavlauncher/src/main/java/com/kdt/mcgui/MineButton.java index d5cbc7042..6b17cd7a1 100644 --- a/app_pojavlauncher/src/main/java/com/kdt/mcgui/MineButton.java +++ b/app_pojavlauncher/src/main/java/com/kdt/mcgui/MineButton.java @@ -8,8 +8,7 @@ import androidx.core.content.res.ResourcesCompat; import net.kdt.pojavlaunch.R; -public class MineButton extends androidx.appcompat.widget.AppCompatButton -{ +public class MineButton extends androidx.appcompat.widget.AppCompatButton { public MineButton(Context ctx) { this(ctx, null); diff --git a/app_pojavlauncher/src/main/java/com/kdt/mcgui/MineEditText.java b/app_pojavlauncher/src/main/java/com/kdt/mcgui/MineEditText.java index 47e83cc9d..61315f928 100644 --- a/app_pojavlauncher/src/main/java/com/kdt/mcgui/MineEditText.java +++ b/app_pojavlauncher/src/main/java/com/kdt/mcgui/MineEditText.java @@ -4,22 +4,18 @@ import android.content.*; import android.util.*; import android.graphics.*; -public class MineEditText extends com.google.android.material.textfield.TextInputEditText -{ - public MineEditText(Context ctx) - { +public class MineEditText extends com.google.android.material.textfield.TextInputEditText { + public MineEditText(Context ctx) { super(ctx); init(); } - public MineEditText(Context ctx, AttributeSet attrs) - { + public MineEditText(Context ctx, AttributeSet attrs) { super(ctx, attrs); init(); } - public void init() - { + public void init() { setBackgroundColor(Color.parseColor("#131313")); setPadding(5, 5, 5, 5); } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/AWTCanvasView.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/AWTCanvasView.java index f9183f1b9..9bf6a5f21 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/AWTCanvasView.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/AWTCanvasView.java @@ -10,56 +10,20 @@ import net.kdt.pojavlaunch.utils.*; import org.lwjgl.glfw.*; public class AWTCanvasView extends TextureView implements TextureView.SurfaceTextureListener, Runnable { + private final int MAX_SIZE = 100; + private final double NANOS = 1000000000.0; + private int mScaleFactor; private int[] mScales; private int mWidth, mHeight; private boolean mIsDestroyed = false; - - private TextPaint fpsPaint; - private boolean attached = false; + private final TextPaint mFpsPaint; + private boolean mAttached = false; + private boolean mDrawing; // Temporary count fps https://stackoverflow.com/a/13729241 - private LinkedList times = new LinkedList(){{add(System.nanoTime());}}; - private final int MAX_SIZE = 100; - private final double NANOS = 1000000000.0; - - /** Calculates and returns frames per second */ - private double fps() { - long lastTime = System.nanoTime(); - double difference = (lastTime - times.getFirst()) / NANOS; - times.addLast(lastTime); - int size = times.size(); - if (size > MAX_SIZE) { - times.removeFirst(); - } - return difference > 0 ? times.size() / difference : 0.0; - } - - /** Computes the scale to better fit the screen */ - void initScaleFactors(){ - initScaleFactors(0); - } - - void initScaleFactors(int forcedScale){ - //Could be optimized - if(forcedScale < 1) { //Auto scale - int minDimension = Math.min(CallbackBridge.physicalHeight, CallbackBridge.physicalWidth); - mScaleFactor = Math.max(((3 * minDimension) / 1080) - 1, 1); - }else{ - mScaleFactor = forcedScale; - } - - int[] scales = new int[2]; //Left, Top - - scales[0] = (CallbackBridge.physicalWidth/2); - scales[0] -= scales[0]/mScaleFactor; - - scales[1] = (CallbackBridge.physicalHeight/2); - scales[1] -= scales[1]/mScaleFactor; - - mScales = scales; - } + private final LinkedList mTimes = new LinkedList(){{add(System.nanoTime());}}; public AWTCanvasView(Context ctx) { this(ctx, null); @@ -67,11 +31,10 @@ public class AWTCanvasView extends TextureView implements TextureView.SurfaceTex public AWTCanvasView(Context ctx, AttributeSet attrs) { super(ctx, attrs); - // setWillNotDraw(false); - fpsPaint = new TextPaint(); - fpsPaint.setColor(Color.WHITE); - fpsPaint.setTextSize(20); + mFpsPaint = new TextPaint(); + mFpsPaint.setColor(Color.WHITE); + mFpsPaint.setTextSize(20); setSurfaceTextureListener(this); initScaleFactors(); @@ -101,21 +64,19 @@ public class AWTCanvasView extends TextureView implements TextureView.SurfaceTex @Override public void onSurfaceTextureUpdated(SurfaceTexture texture) { } - - private boolean mDrawing; - private Surface mSurface; + @Override public void run() { Canvas canvas; - mSurface = new Surface(getSurfaceTexture()); + Surface surface = new Surface(getSurfaceTexture()); try { - while (!mIsDestroyed && mSurface.isValid()) { - canvas = mSurface.lockCanvas(null); + while (!mIsDestroyed && surface.isValid()) { + canvas = surface.lockCanvas(null); canvas.drawRGB(0, 0, 0); - if (!attached) { - attached = CallbackBridge.nativeAttachThreadToOther(true, BaseMainActivity.isInputStackCall); + if (!mAttached) { + mAttached = CallbackBridge.nativeAttachThreadToOther(true, BaseMainActivity.isInputStackCall); } else { int[] rgbArray = JREUtils.renderAWTScreenFrame(/* canvas, mWidth, mHeight */); mDrawing = rgbArray != null; @@ -123,22 +84,55 @@ public class AWTCanvasView extends TextureView implements TextureView.SurfaceTex canvas.save(); canvas.scale(mScaleFactor, mScaleFactor); - canvas.translate(-mScales[0],-mScales[1]); - + canvas.translate(-mScales[0], -mScales[1]); canvas.drawBitmap(rgbArray, 0, CallbackBridge.physicalWidth, 0, 0, CallbackBridge.physicalWidth, CallbackBridge.physicalHeight, true, null); canvas.restore(); - } - rgbArray = null; - // System.gc(); } - canvas.drawText("FPS: " + (Math.round(fps() * 10) / 10) + ", attached=" + attached + ", drawing=" + mDrawing, 50, 50, fpsPaint); - - mSurface.unlockCanvasAndPost(canvas); + canvas.drawText("FPS: " + (Math.round(fps() * 10) / 10) + ", attached=" + mAttached + ", drawing=" + mDrawing, 50, 50, mFpsPaint); + surface.unlockCanvasAndPost(canvas); } - } catch (Throwable th) { - Tools.showError(getContext(), th); + } catch (Throwable throwable) { + Tools.showError(getContext(), throwable); } + surface.release(); + } + + /** Computes the scale to better fit the screen */ + void initScaleFactors(){ + initScaleFactors(0); + } + + void initScaleFactors(int forcedScale){ + //Could be optimized + if(forcedScale < 1) { //Auto scale + int minDimension = Math.min(CallbackBridge.physicalHeight, CallbackBridge.physicalWidth); + mScaleFactor = Math.max(((3 * minDimension) / 1080) - 1, 1); + }else{ + mScaleFactor = forcedScale; + } + + int[] scales = new int[2]; //Left, Top + + scales[0] = (CallbackBridge.physicalWidth/2); + scales[0] -= scales[0]/mScaleFactor; + + scales[1] = (CallbackBridge.physicalHeight/2); + scales[1] -= scales[1]/mScaleFactor; + + mScales = scales; + } + + /** Calculates and returns frames per second */ + private double fps() { + long lastTime = System.nanoTime(); + double difference = (lastTime - mTimes.getFirst()) / NANOS; + mTimes.addLast(lastTime); + int size = mTimes.size(); + if (size > MAX_SIZE) { + mTimes.removeFirst(); + } + return difference > 0 ? mTimes.size() / difference : 0.0; } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/AWTInputEvent.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/AWTInputEvent.java index de924007d..58217ec26 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/AWTInputEvent.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/AWTInputEvent.java @@ -24,8 +24,7 @@ package net.kdt.pojavlaunch; * or visit www.oracle.com if you need additional information or have any * questions. */ -public class AWTInputEvent -{ +public class AWTInputEvent { // InputEvent /** * This flag indicates that the Shift key was down when the event diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseActivity.java index 1b7710b3a..04347eeea 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseActivity.java @@ -7,8 +7,7 @@ import net.kdt.pojavlaunch.utils.*; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_IGNORE_NOTCH; -public class BaseActivity extends AppCompatActivity -{ +public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -24,7 +23,7 @@ public class BaseActivity extends AppCompatActivity @Override public void startActivity(Intent i) { super.startActivity(i); - new Throwable("StartActivity").printStackTrace(); + //new Throwable("StartActivity").printStackTrace(); } @Override diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java index 0292458a0..cab45e470 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java @@ -4,22 +4,16 @@ import static net.kdt.pojavlaunch.Tools.getFileName; import android.app.*; import android.content.*; -import android.database.Cursor; import android.net.Uri; -import android.provider.OpenableColumns; -import android.text.*; -import android.text.method.*; import android.view.*; import android.webkit.MimeTypeMap; import android.widget.*; import androidx.annotation.Nullable; -import androidx.appcompat.app.*; -import com.kdt.pickafile.*; + import java.io.*; import java.util.ArrayList; import java.util.Map; - import net.kdt.pojavlaunch.extra.ExtraCore; import net.kdt.pojavlaunch.extra.ExtraListener; import net.kdt.pojavlaunch.fragments.*; @@ -74,7 +68,7 @@ public abstract class BaseLauncherActivity extends BaseActivity { public static final int RUN_MOD_INSTALLER = 2050; private void installMod(boolean customJavaArgs) { - if (MultiRTUtils.getExactJREName(8) == null) { + if (MultiRTUtils.getExactJreName(8) == null) { Toast.makeText(this, R.string.multirt_nojava8rt, Toast.LENGTH_LONG).show(); return; } @@ -118,6 +112,19 @@ public abstract class BaseLauncherActivity extends BaseActivity { if (LauncherProfiles.mainProfileJson != null && LauncherProfiles.mainProfileJson.profiles != null && LauncherProfiles.mainProfileJson.profiles.containsKey(mProfile.selectedProfile + "")) { MinecraftProfile prof = LauncherProfiles.mainProfileJson.profiles.get(mProfile.selectedProfile + ""); if (prof != null && prof.lastVersionId != null) { + if (mProfile.accessToken.equals("0")) { + File verJsonFile = new File(Tools.DIR_HOME_VERSION, + mProfile.selectedVersion + "/" + mProfile.selectedVersion + ".json"); + if (verJsonFile.exists()) { + mTask.onPostExecute(null); + } else { + new AlertDialog.Builder(this) + .setTitle(R.string.global_error) + .setMessage(R.string.mcl_launch_error_localmode) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + } mTask.execute(getVersionId(prof.lastVersionId)); } } @@ -300,7 +307,7 @@ public abstract class BaseLauncherActivity extends BaseActivity { BaseLauncherActivity.this.runOnUiThread(() -> { barrier.dismiss(); mRuntimeConfigDialog.refresh(); - mRuntimeConfigDialog.dialog.show(); + mRuntimeConfigDialog.mDialog.show(); }); }); t.start(); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java index 6d34a02ed..b8b0ada86 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java @@ -11,7 +11,6 @@ import static org.lwjgl.glfw.CallbackBridge.windowWidth; import android.app.*; import android.content.*; import android.content.pm.PackageManager; -import android.graphics.*; import android.os.*; import android.util.*; import android.view.*; @@ -178,17 +177,31 @@ public class BaseMainActivity extends BaseActivity { final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; final View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility(uiOptions); + CallbackBridge.nativeSetWindowAttrib(LwjglGlfwKeycode.GLFW_HOVERED, 1); } @Override protected void onPause() { if (CallbackBridge.isGrabbing()){ - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_ESCAPE); + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_ESCAPE); } + CallbackBridge.nativeSetWindowAttrib(LwjglGlfwKeycode.GLFW_HOVERED, 0); mIsResuming = false; super.onPause(); } + @Override + protected void onStart() { + super.onStart(); + CallbackBridge.nativeSetWindowAttrib(LwjglGlfwKeycode.GLFW_VISIBLE, 1); + } + + @Override + protected void onStop() { + CallbackBridge.nativeSetWindowAttrib(LwjglGlfwKeycode.GLFW_VISIBLE, 0); + super.onStop(); + } + public static void fullyExit() { android.os.Process.killProcess(android.os.Process.myPid()); } @@ -217,6 +230,7 @@ public class BaseMainActivity extends BaseActivity { ((mVersionInfo.inheritsFrom == null || mVersionInfo.inheritsFrom.equals(mVersionInfo.id)) ? "" : " (" + mVersionInfo.inheritsFrom + ")")); + JREUtils.redirectAndPrintJRELog(this); if(!LauncherPreferences.PREF_ENABLE_PROFILES){ Tools.launchMinecraft(this, mProfile, mProfile.selectedVersion); @@ -225,7 +239,6 @@ public class BaseMainActivity extends BaseActivity { Tools.launchMinecraft(this, mProfile, BaseLauncherActivity.getVersionId( LauncherProfiles.mainProfileJson.profiles.get(mProfile.selectedProfile).lastVersionId)); } - } private void checkJavaArgsIsLaunchable(String jreVersion) throws Throwable { @@ -347,7 +360,7 @@ public class BaseMainActivity extends BaseActivity { public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && !touchCharInput.isEnabled()) { if(event.getAction() != KeyEvent.ACTION_UP) return true; // We eat it anyway - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_ESCAPE); + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_ESCAPE); return true; } return super.dispatchKeyEvent(event); @@ -362,7 +375,7 @@ public class BaseMainActivity extends BaseActivity { public void adjustMouseSpeedLive() { AlertDialog.Builder b = new AlertDialog.Builder(this); b.setTitle(R.string.mcl_setting_title_mousespeed); - View v = LayoutInflater.from(this).inflate(R.layout.live_mouse_speed_editor,null); + View v = LayoutInflater.from(this).inflate(R.layout.dialog_live_mouse_speed_editor,null); final SeekBar sb = v.findViewById(R.id.mouseSpeed); final TextView tv = v.findViewById(R.id.mouseSpeedTV); sb.setMax(275); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/CustomControlsActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/CustomControlsActivity.java index 92795cd21..c694b9307 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/CustomControlsActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/CustomControlsActivity.java @@ -5,13 +5,13 @@ import android.content.*; import android.os.*; import androidx.appcompat.app.*; -import androidx.preference.*; -import android.view.*; + import android.widget.*; import androidx.drawerlayout.widget.DrawerLayout; import com.google.android.material.navigation.NavigationView; +import com.google.gson.JsonSyntaxException; import com.kdt.pickafile.*; import java.io.*; @@ -19,18 +19,13 @@ import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.customcontrols.*; - -public class CustomControlsActivity extends BaseActivity -{ - private DrawerLayout drawerLayout; - private NavigationView navDrawer; - private ControlLayout ctrlLayout; - - private SharedPreferences mPref; +public class CustomControlsActivity extends BaseActivity { + private DrawerLayout mDrawerLayout; + private NavigationView mDrawerNavigationView; + private ControlLayout mControlLayout; public boolean isModified = false; - public boolean isFromMainActivity = false; - private static String selectedName = "new_control"; + private static String sSelectedName = "new_control"; @Override protected void onCreate(Bundle savedInstanceState) { @@ -41,48 +36,41 @@ public class CustomControlsActivity extends BaseActivity // setTheme(androidx.appcompat.R.style.Theme_AppCompat_Translucent); } - setContentView(R.layout.control_mapping); - - mPref = PreferenceManager.getDefaultSharedPreferences(this); + setContentView(R.layout.activity_custom_controls); - ctrlLayout = (ControlLayout) findViewById(R.id.customctrl_controllayout); + mControlLayout = (ControlLayout) findViewById(R.id.customctrl_controllayout); + mDrawerLayout = (DrawerLayout) findViewById(R.id.customctrl_drawerlayout); + mDrawerNavigationView = (NavigationView) findViewById(R.id.customctrl_navigation_view); - // Menu - drawerLayout = (DrawerLayout) findViewById(R.id.customctrl_drawerlayout); - - navDrawer = (NavigationView) findViewById(R.id.customctrl_navigation_view); - navDrawer.setNavigationItemSelectedListener( - new NavigationView.OnNavigationItemSelectedListener() { - @Override - public boolean onNavigationItemSelected(MenuItem menuItem) { + mDrawerNavigationView.setNavigationItemSelectedListener( + menuItem -> { switch (menuItem.getItemId()) { case R.id.menu_ctrl_load: - load(ctrlLayout); + load(mControlLayout); break; case R.id.menu_ctrl_add: - ctrlLayout.addControlButton(new ControlData("New")); + mControlLayout.addControlButton(new ControlData("New")); break; case R.id.menu_ctrl_add_drawer: - ctrlLayout.addDrawer(new ControlDrawerData()); + mControlLayout.addDrawer(new ControlDrawerData()); break; case R.id.menu_ctrl_selectdefault: - dialogSelectDefaultCtrl(ctrlLayout); + dialogSelectDefaultCtrl(mControlLayout); break; case R.id.menu_ctrl_save: - save(false,ctrlLayout); + save(false, mControlLayout); break; } //Toast.makeText(MainActivity.this, menuItem.getTitle() + ":" + menuItem.getItemId(), Toast.LENGTH_SHORT).show(); - drawerLayout.closeDrawers(); + mDrawerLayout.closeDrawers(); return true; - } - }); + }); - ctrlLayout.setActivity(this); - ctrlLayout.setModifiable(true); + mControlLayout.setActivity(this); + mControlLayout.setModifiable(true); - loadControl(LauncherPreferences.PREF_DEFAULTCTRL_PATH,ctrlLayout); + loadControl(LauncherPreferences.PREF_DEFAULTCTRL_PATH, mControlLayout); } @Override @@ -93,18 +81,7 @@ public class CustomControlsActivity extends BaseActivity return; } - save(true,ctrlLayout); - } - - private static void setDefaultControlJson(String path,ControlLayout ctrlLayout) { - try { - // Load before save to make sure control is not error - ctrlLayout.loadLayout(Tools.GLOBAL_GSON.fromJson(Tools.read(path), CustomControls.class)); - LauncherPreferences.DEFAULT_PREF.edit().putString("defaultCtrl", path).commit(); - LauncherPreferences.PREF_DEFAULTCTRL_PATH = path; - } catch (Throwable th) { - Tools.showError(ctrlLayout.getContext(), th); - } + save(true, mControlLayout); } public static void dialogSelectDefaultCtrl(final ControlLayout layout) { @@ -127,18 +104,12 @@ public class CustomControlsActivity extends BaseActivity dialog.show(); } - private static String doSaveCtrl(String name, final ControlLayout layout) throws Exception { - String jsonPath = Tools.CTRLMAP_PATH + "/" + name + ".json"; - layout.saveLayout(jsonPath); - - return jsonPath; - } public static void save(final boolean exit, final ControlLayout layout) { final Context ctx = layout.getContext(); final EditText edit = new EditText(ctx); edit.setSingleLine(); - edit.setText(selectedName); + edit.setText(sSelectedName); AlertDialog.Builder builder = new AlertDialog.Builder(ctx); builder.setTitle(R.string.global_save); @@ -162,51 +133,38 @@ public class CustomControlsActivity extends BaseActivity }); } final AlertDialog dialog = builder.create(); - dialog.setOnShowListener(new DialogInterface.OnShowListener() { + dialog.setOnShowListener(dialogInterface -> { - @Override - public void onShow(DialogInterface dialogInterface) { - - Button button = dialog.getButton(AlertDialog.BUTTON_POSITIVE); - button.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View view) { - if (edit.getText().toString().isEmpty()) { - edit.setError(ctx.getResources().getString(R.string.global_error_field_empty)); - } else { - try { - String jsonPath = doSaveCtrl(edit.getText().toString(),layout); - - Toast.makeText(ctx, ctx.getString(R.string.global_save) + ": " + jsonPath, Toast.LENGTH_SHORT).show(); - - dialog.dismiss(); - if (exit) { - if(ctx instanceof MainActivity) { - ((MainActivity) ctx).leaveCustomControls(); - }else{ - ((Activity)ctx).onBackPressed(); - } - //CustomControlsActivity.super.onBackPressed(); - } - } catch (Throwable th) { - Tools.showError(ctx, th, exit); - } - } - } - }); + Button button = dialog.getButton(AlertDialog.BUTTON_POSITIVE); + button.setOnClickListener(view -> { + if (edit.getText().toString().isEmpty()) { + edit.setError(ctx.getResources().getString(R.string.global_error_field_empty)); + return; } + + try { + String jsonPath = doSaveCtrl(edit.getText().toString(),layout); + Toast.makeText(ctx, ctx.getString(R.string.global_save) + ": " + jsonPath, Toast.LENGTH_SHORT).show(); + + dialog.dismiss(); + if (!exit) return; + + if(ctx instanceof MainActivity) { + ((MainActivity) ctx).leaveCustomControls(); + }else{ + ((Activity)ctx).onBackPressed(); + } + } catch (Throwable th) { + Tools.showError(ctx, th, exit); + } + }); + }); dialog.show(); } public static void load(final ControlLayout layout) { - /*ControlJsonSelector sel = new ControlJsonSelector(layout.getContext(), R.string.global_load); - sel.setFinishCallback((f)->{ - loadControl(f.getAbsolutePath(),layout); - }); - sel.show();*/ AlertDialog.Builder builder = new AlertDialog.Builder(layout.getContext()); builder.setTitle(R.string.global_load); builder.setPositiveButton(android.R.string.cancel, null); @@ -227,12 +185,30 @@ public class CustomControlsActivity extends BaseActivity dialog.show(); } + private static void setDefaultControlJson(String path,ControlLayout ctrlLayout) { + // Load before save to make sure control is not error + try { + ctrlLayout.loadLayout(Tools.GLOBAL_GSON.fromJson(Tools.read(path), CustomControls.class)); + LauncherPreferences.DEFAULT_PREF.edit().putString("defaultCtrl", path).apply(); + LauncherPreferences.PREF_DEFAULTCTRL_PATH = path; + } catch (IOException| JsonSyntaxException exception) { + Tools.showError(ctrlLayout.getContext(), exception); + } + } + + private static String doSaveCtrl(String name, final ControlLayout layout) throws Exception { + String jsonPath = Tools.CTRLMAP_PATH + "/" + name + ".json"; + layout.saveLayout(jsonPath); + + return jsonPath; + } + private static void loadControl(String path,ControlLayout layout) { try { layout.loadLayout(path); - selectedName = new File(path).getName(); + sSelectedName = new File(path).getName(); // Remove `.json` - selectedName = selectedName.substring(0, selectedName.length() - 5); + sSelectedName = sSelectedName.substring(0, sSelectedName.length() - 5); } catch (Exception e) { Tools.showError(layout.getContext(), e); } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/CustomTabs.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/CustomTabs.java deleted file mode 100644 index 5f99814ce..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/CustomTabs.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.kdt.pojavlaunch; - -import android.content.*; -import android.net.*; -import androidx.browser.customtabs.*; - -public class CustomTabs { - - public static void openTab(Context context, String url) { - CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); - builder.setShowTitle(true); - - CustomTabsIntent customTabsIntent = builder.build(); - customTabsIntent.launchUrl(context, Uri.parse(url)); - } -} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/EfficientAndroidLWJGLKeycode.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/EfficientAndroidLWJGLKeycode.java index a7677b4c0..dfc650ad1 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/EfficientAndroidLWJGLKeycode.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/EfficientAndroidLWJGLKeycode.java @@ -4,8 +4,6 @@ import static org.lwjgl.glfw.CallbackBridge.sendKeyPress; import android.view.KeyEvent; -import net.kdt.pojavlaunch.prefs.LauncherPreferences; - import org.lwjgl.glfw.CallbackBridge; import java.util.Arrays; @@ -16,168 +14,158 @@ public class EfficientAndroidLWJGLKeycode { //The key being the android keycode from a KeyEvent //The value its LWJGL equivalent. private static final int KEYCODE_COUNT = 103; - private static final int[] androidKeycodes = new int[KEYCODE_COUNT]; - private static final short[] LWJGLKeycodes = new short[KEYCODE_COUNT]; + private static final int[] sAndroidKeycodes = new int[KEYCODE_COUNT]; + private static final short[] sLwjglKeycodes = new short[KEYCODE_COUNT]; private static String[] androidKeyNameArray; /* = new String[androidKeycodes.length]; */ + private static int mTmpCount = 0; static { /* BINARY SEARCH IS PERFORMED ON THE androidKeycodes ARRAY ! WHEN ADDING A MAPPING, ADD IT SO THE androidKeycodes ARRAY STAYS SORTED ! */ // Mapping Android Keycodes to LWJGL Keycodes - add(KeyEvent.KEYCODE_UNKNOWN,LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN); - add(KeyEvent.KEYCODE_HOME, LWJGLGLFWKeycode.GLFW_KEY_HOME); + add(KeyEvent.KEYCODE_UNKNOWN, LwjglGlfwKeycode.GLFW_KEY_UNKNOWN); + add(KeyEvent.KEYCODE_HOME, LwjglGlfwKeycode.GLFW_KEY_HOME); // Escape key - add(KeyEvent.KEYCODE_BACK, LWJGLGLFWKeycode.GLFW_KEY_ESCAPE); + add(KeyEvent.KEYCODE_BACK, LwjglGlfwKeycode.GLFW_KEY_ESCAPE); // 0-9 keys - add(KeyEvent.KEYCODE_0, LWJGLGLFWKeycode.GLFW_KEY_0); //7 - add(KeyEvent.KEYCODE_1, LWJGLGLFWKeycode.GLFW_KEY_1); - add(KeyEvent.KEYCODE_2, LWJGLGLFWKeycode.GLFW_KEY_2); - add(KeyEvent.KEYCODE_3, LWJGLGLFWKeycode.GLFW_KEY_3); - add(KeyEvent.KEYCODE_4, LWJGLGLFWKeycode.GLFW_KEY_4); - add(KeyEvent.KEYCODE_5, LWJGLGLFWKeycode.GLFW_KEY_5); - add(KeyEvent.KEYCODE_6, LWJGLGLFWKeycode.GLFW_KEY_6); - add(KeyEvent.KEYCODE_7, LWJGLGLFWKeycode.GLFW_KEY_7); - add(KeyEvent.KEYCODE_8, LWJGLGLFWKeycode.GLFW_KEY_8); - add(KeyEvent.KEYCODE_9, LWJGLGLFWKeycode.GLFW_KEY_9); //16 + add(KeyEvent.KEYCODE_0, LwjglGlfwKeycode.GLFW_KEY_0); //7 + add(KeyEvent.KEYCODE_1, LwjglGlfwKeycode.GLFW_KEY_1); + add(KeyEvent.KEYCODE_2, LwjglGlfwKeycode.GLFW_KEY_2); + add(KeyEvent.KEYCODE_3, LwjglGlfwKeycode.GLFW_KEY_3); + add(KeyEvent.KEYCODE_4, LwjglGlfwKeycode.GLFW_KEY_4); + add(KeyEvent.KEYCODE_5, LwjglGlfwKeycode.GLFW_KEY_5); + add(KeyEvent.KEYCODE_6, LwjglGlfwKeycode.GLFW_KEY_6); + add(KeyEvent.KEYCODE_7, LwjglGlfwKeycode.GLFW_KEY_7); + add(KeyEvent.KEYCODE_8, LwjglGlfwKeycode.GLFW_KEY_8); + add(KeyEvent.KEYCODE_9, LwjglGlfwKeycode.GLFW_KEY_9); //16 - add(KeyEvent.KEYCODE_POUND,LWJGLGLFWKeycode.GLFW_KEY_3); + add(KeyEvent.KEYCODE_POUND, LwjglGlfwKeycode.GLFW_KEY_3); // Arrow keys - add(KeyEvent.KEYCODE_DPAD_UP, LWJGLGLFWKeycode.GLFW_KEY_UP); //19 - add(KeyEvent.KEYCODE_DPAD_DOWN, LWJGLGLFWKeycode.GLFW_KEY_DOWN); - add(KeyEvent.KEYCODE_DPAD_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT); - add(KeyEvent.KEYCODE_DPAD_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT); //22 + add(KeyEvent.KEYCODE_DPAD_UP, LwjglGlfwKeycode.GLFW_KEY_UP); //19 + add(KeyEvent.KEYCODE_DPAD_DOWN, LwjglGlfwKeycode.GLFW_KEY_DOWN); + add(KeyEvent.KEYCODE_DPAD_LEFT, LwjglGlfwKeycode.GLFW_KEY_LEFT); + add(KeyEvent.KEYCODE_DPAD_RIGHT, LwjglGlfwKeycode.GLFW_KEY_RIGHT); //22 // A-Z keys - add(KeyEvent.KEYCODE_A, LWJGLGLFWKeycode.GLFW_KEY_A); //29 - add(KeyEvent.KEYCODE_B, LWJGLGLFWKeycode.GLFW_KEY_B); - add(KeyEvent.KEYCODE_C, LWJGLGLFWKeycode.GLFW_KEY_C); - add(KeyEvent.KEYCODE_D, LWJGLGLFWKeycode.GLFW_KEY_D); - add(KeyEvent.KEYCODE_E, LWJGLGLFWKeycode.GLFW_KEY_E); - add(KeyEvent.KEYCODE_F, LWJGLGLFWKeycode.GLFW_KEY_F); - add(KeyEvent.KEYCODE_G, LWJGLGLFWKeycode.GLFW_KEY_G); - add(KeyEvent.KEYCODE_H, LWJGLGLFWKeycode.GLFW_KEY_H); - add(KeyEvent.KEYCODE_I, LWJGLGLFWKeycode.GLFW_KEY_I); - add(KeyEvent.KEYCODE_J, LWJGLGLFWKeycode.GLFW_KEY_J); - add(KeyEvent.KEYCODE_K, LWJGLGLFWKeycode.GLFW_KEY_K); - add(KeyEvent.KEYCODE_L, LWJGLGLFWKeycode.GLFW_KEY_L); - add(KeyEvent.KEYCODE_M, LWJGLGLFWKeycode.GLFW_KEY_M); - add(KeyEvent.KEYCODE_N, LWJGLGLFWKeycode.GLFW_KEY_N); - add(KeyEvent.KEYCODE_O, LWJGLGLFWKeycode.GLFW_KEY_O); - add(KeyEvent.KEYCODE_P, LWJGLGLFWKeycode.GLFW_KEY_P); - add(KeyEvent.KEYCODE_Q, LWJGLGLFWKeycode.GLFW_KEY_Q); - add(KeyEvent.KEYCODE_R, LWJGLGLFWKeycode.GLFW_KEY_R); - add(KeyEvent.KEYCODE_S, LWJGLGLFWKeycode.GLFW_KEY_S); - add(KeyEvent.KEYCODE_T, LWJGLGLFWKeycode.GLFW_KEY_T); - add(KeyEvent.KEYCODE_U, LWJGLGLFWKeycode.GLFW_KEY_U); - add(KeyEvent.KEYCODE_V, LWJGLGLFWKeycode.GLFW_KEY_V); - add(KeyEvent.KEYCODE_W, LWJGLGLFWKeycode.GLFW_KEY_W); - add(KeyEvent.KEYCODE_X, LWJGLGLFWKeycode.GLFW_KEY_X); - add(KeyEvent.KEYCODE_Y, LWJGLGLFWKeycode.GLFW_KEY_Y); - add(KeyEvent.KEYCODE_Z, LWJGLGLFWKeycode.GLFW_KEY_Z); //54 + add(KeyEvent.KEYCODE_A, LwjglGlfwKeycode.GLFW_KEY_A); //29 + add(KeyEvent.KEYCODE_B, LwjglGlfwKeycode.GLFW_KEY_B); + add(KeyEvent.KEYCODE_C, LwjglGlfwKeycode.GLFW_KEY_C); + add(KeyEvent.KEYCODE_D, LwjglGlfwKeycode.GLFW_KEY_D); + add(KeyEvent.KEYCODE_E, LwjglGlfwKeycode.GLFW_KEY_E); + add(KeyEvent.KEYCODE_F, LwjglGlfwKeycode.GLFW_KEY_F); + add(KeyEvent.KEYCODE_G, LwjglGlfwKeycode.GLFW_KEY_G); + add(KeyEvent.KEYCODE_H, LwjglGlfwKeycode.GLFW_KEY_H); + add(KeyEvent.KEYCODE_I, LwjglGlfwKeycode.GLFW_KEY_I); + add(KeyEvent.KEYCODE_J, LwjglGlfwKeycode.GLFW_KEY_J); + add(KeyEvent.KEYCODE_K, LwjglGlfwKeycode.GLFW_KEY_K); + add(KeyEvent.KEYCODE_L, LwjglGlfwKeycode.GLFW_KEY_L); + add(KeyEvent.KEYCODE_M, LwjglGlfwKeycode.GLFW_KEY_M); + add(KeyEvent.KEYCODE_N, LwjglGlfwKeycode.GLFW_KEY_N); + add(KeyEvent.KEYCODE_O, LwjglGlfwKeycode.GLFW_KEY_O); + add(KeyEvent.KEYCODE_P, LwjglGlfwKeycode.GLFW_KEY_P); + add(KeyEvent.KEYCODE_Q, LwjglGlfwKeycode.GLFW_KEY_Q); + add(KeyEvent.KEYCODE_R, LwjglGlfwKeycode.GLFW_KEY_R); + add(KeyEvent.KEYCODE_S, LwjglGlfwKeycode.GLFW_KEY_S); + add(KeyEvent.KEYCODE_T, LwjglGlfwKeycode.GLFW_KEY_T); + add(KeyEvent.KEYCODE_U, LwjglGlfwKeycode.GLFW_KEY_U); + add(KeyEvent.KEYCODE_V, LwjglGlfwKeycode.GLFW_KEY_V); + add(KeyEvent.KEYCODE_W, LwjglGlfwKeycode.GLFW_KEY_W); + add(KeyEvent.KEYCODE_X, LwjglGlfwKeycode.GLFW_KEY_X); + add(KeyEvent.KEYCODE_Y, LwjglGlfwKeycode.GLFW_KEY_Y); + add(KeyEvent.KEYCODE_Z, LwjglGlfwKeycode.GLFW_KEY_Z); //54 - add(KeyEvent.KEYCODE_COMMA, LWJGLGLFWKeycode.GLFW_KEY_COMMA); - add(KeyEvent.KEYCODE_PERIOD, LWJGLGLFWKeycode.GLFW_KEY_PERIOD); + add(KeyEvent.KEYCODE_COMMA, LwjglGlfwKeycode.GLFW_KEY_COMMA); + add(KeyEvent.KEYCODE_PERIOD, LwjglGlfwKeycode.GLFW_KEY_PERIOD); // Alt keys - add(KeyEvent.KEYCODE_ALT_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_ALT); - add(KeyEvent.KEYCODE_ALT_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_ALT); + add(KeyEvent.KEYCODE_ALT_LEFT, LwjglGlfwKeycode.GLFW_KEY_LEFT_ALT); + add(KeyEvent.KEYCODE_ALT_RIGHT, LwjglGlfwKeycode.GLFW_KEY_RIGHT_ALT); // Shift keys - add(KeyEvent.KEYCODE_SHIFT_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT); - add(KeyEvent.KEYCODE_SHIFT_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_SHIFT); + add(KeyEvent.KEYCODE_SHIFT_LEFT, LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT); + add(KeyEvent.KEYCODE_SHIFT_RIGHT, LwjglGlfwKeycode.GLFW_KEY_RIGHT_SHIFT); - add(KeyEvent.KEYCODE_TAB, LWJGLGLFWKeycode.GLFW_KEY_TAB); - add(KeyEvent.KEYCODE_SPACE, LWJGLGLFWKeycode.GLFW_KEY_SPACE); - add(KeyEvent.KEYCODE_ENTER, LWJGLGLFWKeycode.GLFW_KEY_ENTER); //66 - add(KeyEvent.KEYCODE_DEL, LWJGLGLFWKeycode.GLFW_KEY_BACKSPACE); // Backspace - add(KeyEvent.KEYCODE_GRAVE, LWJGLGLFWKeycode.GLFW_KEY_GRAVE_ACCENT); - add(KeyEvent.KEYCODE_MINUS, LWJGLGLFWKeycode.GLFW_KEY_MINUS); - add(KeyEvent.KEYCODE_EQUALS, LWJGLGLFWKeycode.GLFW_KEY_EQUAL); - add(KeyEvent.KEYCODE_LEFT_BRACKET, LWJGLGLFWKeycode.GLFW_KEY_LEFT_BRACKET); - add(KeyEvent.KEYCODE_RIGHT_BRACKET, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_BRACKET); - add(KeyEvent.KEYCODE_BACKSLASH, LWJGLGLFWKeycode.GLFW_KEY_BACKSLASH); - add(KeyEvent.KEYCODE_SEMICOLON, LWJGLGLFWKeycode.GLFW_KEY_SEMICOLON); //74 + add(KeyEvent.KEYCODE_TAB, LwjglGlfwKeycode.GLFW_KEY_TAB); + add(KeyEvent.KEYCODE_SPACE, LwjglGlfwKeycode.GLFW_KEY_SPACE); + add(KeyEvent.KEYCODE_ENTER, LwjglGlfwKeycode.GLFW_KEY_ENTER); //66 + add(KeyEvent.KEYCODE_DEL, LwjglGlfwKeycode.GLFW_KEY_BACKSPACE); // Backspace + add(KeyEvent.KEYCODE_GRAVE, LwjglGlfwKeycode.GLFW_KEY_GRAVE_ACCENT); + add(KeyEvent.KEYCODE_MINUS, LwjglGlfwKeycode.GLFW_KEY_MINUS); + add(KeyEvent.KEYCODE_EQUALS, LwjglGlfwKeycode.GLFW_KEY_EQUAL); + add(KeyEvent.KEYCODE_LEFT_BRACKET, LwjglGlfwKeycode.GLFW_KEY_LEFT_BRACKET); + add(KeyEvent.KEYCODE_RIGHT_BRACKET, LwjglGlfwKeycode.GLFW_KEY_RIGHT_BRACKET); + add(KeyEvent.KEYCODE_BACKSLASH, LwjglGlfwKeycode.GLFW_KEY_BACKSLASH); + add(KeyEvent.KEYCODE_SEMICOLON, LwjglGlfwKeycode.GLFW_KEY_SEMICOLON); //74 - add(KeyEvent.KEYCODE_SLASH, LWJGLGLFWKeycode.GLFW_KEY_SLASH); //76 - add(KeyEvent.KEYCODE_AT,LWJGLGLFWKeycode.GLFW_KEY_2); + add(KeyEvent.KEYCODE_SLASH, LwjglGlfwKeycode.GLFW_KEY_SLASH); //76 + add(KeyEvent.KEYCODE_AT, LwjglGlfwKeycode.GLFW_KEY_2); - add(KeyEvent.KEYCODE_PLUS, LWJGLGLFWKeycode.GLFW_KEY_KP_ADD); + add(KeyEvent.KEYCODE_PLUS, LwjglGlfwKeycode.GLFW_KEY_KP_ADD); // Page keys - add(KeyEvent.KEYCODE_PAGE_UP, LWJGLGLFWKeycode.GLFW_KEY_PAGE_UP); //92 - add(KeyEvent.KEYCODE_PAGE_DOWN, LWJGLGLFWKeycode.GLFW_KEY_PAGE_DOWN); + add(KeyEvent.KEYCODE_PAGE_UP, LwjglGlfwKeycode.GLFW_KEY_PAGE_UP); //92 + add(KeyEvent.KEYCODE_PAGE_DOWN, LwjglGlfwKeycode.GLFW_KEY_PAGE_DOWN); - add(KeyEvent.KEYCODE_ESCAPE, LWJGLGLFWKeycode.GLFW_KEY_ESCAPE); + add(KeyEvent.KEYCODE_ESCAPE, LwjglGlfwKeycode.GLFW_KEY_ESCAPE); // Control keys - add(KeyEvent.KEYCODE_CTRL_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL); - add(KeyEvent.KEYCODE_CTRL_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_CONTROL); + add(KeyEvent.KEYCODE_CTRL_LEFT, LwjglGlfwKeycode.GLFW_KEY_LEFT_CONTROL); + add(KeyEvent.KEYCODE_CTRL_RIGHT, LwjglGlfwKeycode.GLFW_KEY_RIGHT_CONTROL); - add(KeyEvent.KEYCODE_CAPS_LOCK, LWJGLGLFWKeycode.GLFW_KEY_CAPS_LOCK); - add(KeyEvent.KEYCODE_BREAK, LWJGLGLFWKeycode.GLFW_KEY_PAUSE); - add(KeyEvent.KEYCODE_INSERT, LWJGLGLFWKeycode.GLFW_KEY_INSERT); + add(KeyEvent.KEYCODE_CAPS_LOCK, LwjglGlfwKeycode.GLFW_KEY_CAPS_LOCK); + add(KeyEvent.KEYCODE_BREAK, LwjglGlfwKeycode.GLFW_KEY_PAUSE); + add(KeyEvent.KEYCODE_INSERT, LwjglGlfwKeycode.GLFW_KEY_INSERT); // Fn keys - add(KeyEvent.KEYCODE_F1, LWJGLGLFWKeycode.GLFW_KEY_F1); //131 - add(KeyEvent.KEYCODE_F2, LWJGLGLFWKeycode.GLFW_KEY_F2); - add(KeyEvent.KEYCODE_F3, LWJGLGLFWKeycode.GLFW_KEY_F3); - add(KeyEvent.KEYCODE_F4, LWJGLGLFWKeycode.GLFW_KEY_F4); - add(KeyEvent.KEYCODE_F5, LWJGLGLFWKeycode.GLFW_KEY_F5); - add(KeyEvent.KEYCODE_F6, LWJGLGLFWKeycode.GLFW_KEY_F6); - add(KeyEvent.KEYCODE_F7, LWJGLGLFWKeycode.GLFW_KEY_F7); - add(KeyEvent.KEYCODE_F8, LWJGLGLFWKeycode.GLFW_KEY_F8); - add(KeyEvent.KEYCODE_F9, LWJGLGLFWKeycode.GLFW_KEY_F9); - add(KeyEvent.KEYCODE_F10, LWJGLGLFWKeycode.GLFW_KEY_F10); - add(KeyEvent.KEYCODE_F11, LWJGLGLFWKeycode.GLFW_KEY_F11); - add(KeyEvent.KEYCODE_F12, LWJGLGLFWKeycode.GLFW_KEY_F12); //142 + add(KeyEvent.KEYCODE_F1, LwjglGlfwKeycode.GLFW_KEY_F1); //131 + add(KeyEvent.KEYCODE_F2, LwjglGlfwKeycode.GLFW_KEY_F2); + add(KeyEvent.KEYCODE_F3, LwjglGlfwKeycode.GLFW_KEY_F3); + add(KeyEvent.KEYCODE_F4, LwjglGlfwKeycode.GLFW_KEY_F4); + add(KeyEvent.KEYCODE_F5, LwjglGlfwKeycode.GLFW_KEY_F5); + add(KeyEvent.KEYCODE_F6, LwjglGlfwKeycode.GLFW_KEY_F6); + add(KeyEvent.KEYCODE_F7, LwjglGlfwKeycode.GLFW_KEY_F7); + add(KeyEvent.KEYCODE_F8, LwjglGlfwKeycode.GLFW_KEY_F8); + add(KeyEvent.KEYCODE_F9, LwjglGlfwKeycode.GLFW_KEY_F9); + add(KeyEvent.KEYCODE_F10, LwjglGlfwKeycode.GLFW_KEY_F10); + add(KeyEvent.KEYCODE_F11, LwjglGlfwKeycode.GLFW_KEY_F11); + add(KeyEvent.KEYCODE_F12, LwjglGlfwKeycode.GLFW_KEY_F12); //142 // Num keys - add(KeyEvent.KEYCODE_NUM_LOCK, LWJGLGLFWKeycode.GLFW_KEY_NUM_LOCK); //143 - add(KeyEvent.KEYCODE_NUMPAD_0, LWJGLGLFWKeycode.GLFW_KEY_0); - add(KeyEvent.KEYCODE_NUMPAD_1, LWJGLGLFWKeycode.GLFW_KEY_1); - add(KeyEvent.KEYCODE_NUMPAD_2, LWJGLGLFWKeycode.GLFW_KEY_2); - add(KeyEvent.KEYCODE_NUMPAD_3, LWJGLGLFWKeycode.GLFW_KEY_3); - add(KeyEvent.KEYCODE_NUMPAD_4, LWJGLGLFWKeycode.GLFW_KEY_4); - add(KeyEvent.KEYCODE_NUMPAD_5, LWJGLGLFWKeycode.GLFW_KEY_5); - add(KeyEvent.KEYCODE_NUMPAD_6, LWJGLGLFWKeycode.GLFW_KEY_6); - add(KeyEvent.KEYCODE_NUMPAD_7, LWJGLGLFWKeycode.GLFW_KEY_7); - add(KeyEvent.KEYCODE_NUMPAD_8, LWJGLGLFWKeycode.GLFW_KEY_8); - add(KeyEvent.KEYCODE_NUMPAD_9, LWJGLGLFWKeycode.GLFW_KEY_9); - add(KeyEvent.KEYCODE_NUMPAD_DIVIDE, LWJGLGLFWKeycode.GLFW_KEY_KP_DIVIDE); - add(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, LWJGLGLFWKeycode.GLFW_KEY_KP_MULTIPLY); - add(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, LWJGLGLFWKeycode.GLFW_KEY_KP_SUBTRACT); - add(KeyEvent.KEYCODE_NUMPAD_ADD, LWJGLGLFWKeycode.GLFW_KEY_KP_ADD); - add(KeyEvent.KEYCODE_NUMPAD_DOT, LWJGLGLFWKeycode.GLFW_KEY_PERIOD); - add(KeyEvent.KEYCODE_NUMPAD_COMMA, LWJGLGLFWKeycode.GLFW_KEY_COMMA); - add(KeyEvent.KEYCODE_NUMPAD_ENTER, LWJGLGLFWKeycode.GLFW_KEY_ENTER); - add(KeyEvent.KEYCODE_NUMPAD_EQUALS, LWJGLGLFWKeycode.GLFW_KEY_EQUAL); //161 + add(KeyEvent.KEYCODE_NUM_LOCK, LwjglGlfwKeycode.GLFW_KEY_NUM_LOCK); //143 + add(KeyEvent.KEYCODE_NUMPAD_0, LwjglGlfwKeycode.GLFW_KEY_0); + add(KeyEvent.KEYCODE_NUMPAD_1, LwjglGlfwKeycode.GLFW_KEY_1); + add(KeyEvent.KEYCODE_NUMPAD_2, LwjglGlfwKeycode.GLFW_KEY_2); + add(KeyEvent.KEYCODE_NUMPAD_3, LwjglGlfwKeycode.GLFW_KEY_3); + add(KeyEvent.KEYCODE_NUMPAD_4, LwjglGlfwKeycode.GLFW_KEY_4); + add(KeyEvent.KEYCODE_NUMPAD_5, LwjglGlfwKeycode.GLFW_KEY_5); + add(KeyEvent.KEYCODE_NUMPAD_6, LwjglGlfwKeycode.GLFW_KEY_6); + add(KeyEvent.KEYCODE_NUMPAD_7, LwjglGlfwKeycode.GLFW_KEY_7); + add(KeyEvent.KEYCODE_NUMPAD_8, LwjglGlfwKeycode.GLFW_KEY_8); + add(KeyEvent.KEYCODE_NUMPAD_9, LwjglGlfwKeycode.GLFW_KEY_9); + add(KeyEvent.KEYCODE_NUMPAD_DIVIDE, LwjglGlfwKeycode.GLFW_KEY_KP_DIVIDE); + add(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, LwjglGlfwKeycode.GLFW_KEY_KP_MULTIPLY); + add(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, LwjglGlfwKeycode.GLFW_KEY_KP_SUBTRACT); + add(KeyEvent.KEYCODE_NUMPAD_ADD, LwjglGlfwKeycode.GLFW_KEY_KP_ADD); + add(KeyEvent.KEYCODE_NUMPAD_DOT, LwjglGlfwKeycode.GLFW_KEY_PERIOD); + add(KeyEvent.KEYCODE_NUMPAD_COMMA, LwjglGlfwKeycode.GLFW_KEY_COMMA); + add(KeyEvent.KEYCODE_NUMPAD_ENTER, LwjglGlfwKeycode.GLFW_KEY_ENTER); + add(KeyEvent.KEYCODE_NUMPAD_EQUALS, LwjglGlfwKeycode.GLFW_KEY_EQUAL); //161 } - private static short index = 0; - - private static void add(int androidKeycode, short LWJGLKeycode){ - androidKeycodes[index] = androidKeycode; - LWJGLKeycodes[index] = LWJGLKeycode; - ++index; - } - - public static boolean containsKey(int keycode){ return getIndexByKey(keycode) >= 0; } - - public static String[] generateKeyName() { if (androidKeyNameArray == null) { - androidKeyNameArray = new String[androidKeycodes.length]; + androidKeyNameArray = new String[sAndroidKeycodes.length]; for(int i=0; i < androidKeyNameArray.length; ++i){ - androidKeyNameArray[i] = KeyEvent.keyCodeToString(androidKeycodes[i]).replace("KEYCODE_", ""); + androidKeyNameArray[i] = KeyEvent.keyCodeToString(sAndroidKeycodes[i]).replace("KEYCODE_", ""); } } return androidKeyNameArray; @@ -187,7 +175,6 @@ public class EfficientAndroidLWJGLKeycode { execKey(keyEvent, getIndexByKey(keyEvent.getKeyCode())); } - public static void execKey(KeyEvent keyEvent, int valueIndex) { //valueIndex points to where the value is stored in the array. CallbackBridge.holdingAlt = keyEvent.isAltPressed(); @@ -196,19 +183,14 @@ public class EfficientAndroidLWJGLKeycode { CallbackBridge.holdingNumlock = keyEvent.isNumLockOn(); CallbackBridge.holdingShift = keyEvent.isShiftPressed(); - try { - System.out.println(keyEvent.getKeyCode() + " " +keyEvent.getDisplayLabel()); - char key = (char)(keyEvent.getUnicodeChar() != 0 ? keyEvent.getUnicodeChar() : '\u0000'); - sendKeyPress( - getValueByIndex(valueIndex), - key, - 0, - CallbackBridge.getCurrentMods(), - keyEvent.getAction() == KeyEvent.ACTION_DOWN); - - } catch (Throwable th) { - th.printStackTrace(); - } + System.out.println(keyEvent.getKeyCode() + " " +keyEvent.getDisplayLabel()); + char key = (char)(keyEvent.getUnicodeChar() != 0 ? keyEvent.getUnicodeChar() : '\u0000'); + sendKeyPress( + getValueByIndex(valueIndex), + key, + 0, + CallbackBridge.getCurrentMods(), + keyEvent.getAction() == KeyEvent.ACTION_DOWN); } public static void execKeyIndex(int index){ @@ -217,24 +199,29 @@ public class EfficientAndroidLWJGLKeycode { } public static int getValueByIndex(int index) { - return LWJGLKeycodes[index]; + return sLwjglKeycodes[index]; } public static int getIndexByKey(int key){ - return Arrays.binarySearch(androidKeycodes, key); + return Arrays.binarySearch(sAndroidKeycodes, key); } public static short getValue(int key){ - return LWJGLKeycodes[Arrays.binarySearch(androidKeycodes, key)]; + return sLwjglKeycodes[Arrays.binarySearch(sAndroidKeycodes, key)]; } + /** @return the index at which the key is in the array, searching linearly */ public static int getIndexByValue(int lwjglKey) { - //Since the LWJGL keycodes aren't sorted, linear search is used. //You should avoid using this function on performance critical areas - for (int i = 0; i < LWJGLKeycodes.length; i++) { - if(LWJGLKeycodes[i] == lwjglKey) return i; + for (int i = 0; i < sLwjglKeycodes.length; i++) { + if(sLwjglKeycodes[i] == lwjglKey) return i; } - return 0; } + + private static void add(int androidKeycode, short LWJGLKeycode){ + sAndroidKeycodes[mTmpCount] = androidKeycode; + sLwjglKeycodes[mTmpCount] = LWJGLKeycode; + mTmpCount ++; + } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ExitActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ExitActivity.java index 3ef4e53a9..1fa7de72d 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ExitActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ExitActivity.java @@ -1,6 +1,7 @@ package net.kdt.pojavlaunch; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; @@ -11,13 +12,7 @@ import androidx.appcompat.app.AppCompatActivity; @Keep public class ExitActivity extends AppCompatActivity { - public static void showExitMessage(Context ctx, int code) { - Intent i = new Intent(ctx,ExitActivity.class); - i.putExtra("code",code); - i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - ctx.startActivity(i); - } + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -26,14 +21,20 @@ public class ExitActivity extends AppCompatActivity { if(extras != null) { code = extras.getInt("code",-1); } + new AlertDialog.Builder(this) .setMessage(getString(R.string.mcn_exit_title,code)) - .setPositiveButton(android.R.string.ok,(dialog,which)->{ - dialog.dismiss(); - ExitActivity.this.finish(); - }).setOnCancelListener((z)->{ - ExitActivity.this.finish(); - }) + .setPositiveButton(android.R.string.ok, null) + .setOnDismissListener(dialog -> ExitActivity.this.finish()) .show(); } + + public static void showExitMessage(Context ctx, int code) { + Intent i = new Intent(ctx,ExitActivity.class); + i.putExtra("code",code); + i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + ctx.startActivity(i); + } + } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/FatalErrorActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/FatalErrorActivity.java index c7bb1da41..87dd4f545 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/FatalErrorActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/FatalErrorActivity.java @@ -1,70 +1,47 @@ package net.kdt.pojavlaunch; -import android.app.*; import android.content.*; import android.os.*; import androidx.appcompat.app.*; import android.util.*; import androidx.appcompat.app.AlertDialog; -public class FatalErrorActivity extends AppCompatActivity -{ - public static void showError(Context ctx, String savePath, boolean storageAllow, /* boolean isFatalErr, */ Throwable th) { - Intent ferrorIntent = new Intent(ctx, FatalErrorActivity.class); - ferrorIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - ferrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - ferrorIntent.putExtra("throwable", th); - ferrorIntent.putExtra("savePath", savePath); - ferrorIntent.putExtra("storageAllow", storageAllow); - // ferrorIntent.putExtra("isFatal", isFatalErr); - ctx.startActivity(ferrorIntent); - } - +public class FatalErrorActivity extends AppCompatActivity { + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle extras = getIntent().getExtras(); boolean storageAllow = extras.getBoolean("storageAllow"); - final String strStackTrace = Log.getStackTraceString((Throwable) extras.getSerializable("throwable")); + final String stackTrace = Log.getStackTraceString((Throwable) extras.getSerializable("throwable")); String strSavePath = extras.getString("savePath"); String errHeader = storageAllow ? "Crash stack trace saved to " + strSavePath + "." : "Storage permission is required to save crash stack trace!"; - // boolean isFatalError = extras.getBoolean("isFatal", false); - new AlertDialog.Builder(this) .setTitle(R.string.error_fatal) - .setMessage(errHeader + "\n\n" + strStackTrace) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){ + .setMessage(errHeader + "\n\n" + stackTrace) + .setPositiveButton(android.R.string.ok, (p1, p2) -> finish()) + .setNegativeButton(R.string.global_restart, (p1, p2) -> startActivity(new Intent(FatalErrorActivity.this, PojavLoginActivity.class))) + .setNeutralButton(android.R.string.copy, (p1, p2) -> { + ClipboardManager mgr = (ClipboardManager) FatalErrorActivity.this.getSystemService(CLIPBOARD_SERVICE); + mgr.setPrimaryClip(ClipData.newPlainText("error", stackTrace)); - @Override - public void onClick(DialogInterface p1, int p2) { - finish(); - } + finish(); }) - .setNegativeButton(R.string.global_restart, new DialogInterface.OnClickListener(){ - - @Override - public void onClick(DialogInterface p1, int p2) { - startActivity(new Intent(FatalErrorActivity.this, PojavLoginActivity.class)); - } - }) - .setNeutralButton(android.R.string.copy, new DialogInterface.OnClickListener(){ - - @Override - public void onClick(DialogInterface p1, int p2) { - ClipboardManager mgr = (ClipboardManager) FatalErrorActivity.this.getSystemService(CLIPBOARD_SERVICE); - mgr.setPrimaryClip(ClipData.newPlainText("error", strStackTrace)); - - finish(); - } - }) - //.setNegativeButton("Report (not available)", null) .setCancelable(false) .show(); - - // Tools.showError(this, isFatalError ? R.string.error_fatal : R.string.global_error, th, true); + } + + public static void showError(Context ctx, String savePath, boolean storageAllow, Throwable th) { + Intent ferrorIntent = new Intent(ctx, FatalErrorActivity.class); + ferrorIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + ferrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + ferrorIntent.putExtra("throwable", th); + ferrorIntent.putExtra("savePath", savePath); + ferrorIntent.putExtra("storageAllow", storageAllow); + ctx.startActivity(ferrorIntent); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/GLTextureView.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/GLTextureView.java deleted file mode 100644 index 40af9b420..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/GLTextureView.java +++ /dev/null @@ -1,1821 +0,0 @@ -package net.kdt.pojavlaunch; - -import java.io.Writer; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGL11; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL; -import javax.microedition.khronos.opengles.GL10; -import android.content.Context; -import android.graphics.SurfaceTexture; -import android.opengl.GLDebugHelper; -import android.util.AttributeSet; -import android.util.Log; -import android.view.TextureView; -import android.view.View; - -public class GLTextureView - extends TextureView - implements TextureView.SurfaceTextureListener, - View.OnLayoutChangeListener { - - private final static String TAG = "GLTextureView"; - private final static boolean LOG_ALL = false; - private final static boolean LOG_ATTACH_DETACH = LOG_ALL; - private final static boolean LOG_THREADS = LOG_ALL; - private final static boolean LOG_PAUSE_RESUME = LOG_ALL; - private final static boolean LOG_SURFACE = LOG_ALL; - private final static boolean LOG_RENDERER = LOG_ALL; - private final static boolean LOG_RENDERER_DRAW_FRAME = LOG_ALL; - private final static boolean LOG_EGL = LOG_ALL; - /** - * The renderer only renders - * when the surface is created, or when {@link #requestRender} is called. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - * @see #requestRender() - */ - public final static int RENDERMODE_WHEN_DIRTY = 0; - /** - * The renderer is called - * continuously to re-render the scene. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - */ - public final static int RENDERMODE_CONTINUOUSLY = 1; - - /** - * Check glError() after every GL call and throw an exception if glError indicates - * that an error has occurred. This can be used to help track down which OpenGL ES call - * is causing an error. - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - public final static int DEBUG_CHECK_GL_ERROR = 1; - - /** - * Log GL calls to the system log at "verbose" level with tag "GLTextureView". - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - public final static int DEBUG_LOG_GL_CALLS = 2; - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLTextureView(Context context) { - super(context); - init(); - } - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLTextureView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - @Override - protected void finalize() throws Throwable { - try { - if (mGLThread != null) { - // GLThread may still be running if this view was never - // attached to a window. - mGLThread.requestExitAndWait(); - } - } finally { - super.finalize(); - } - } - - private void init() { - setSurfaceTextureListener(this); - } - - /** - * Set the glWrapper. If the glWrapper is not null, its - * {@link GLWrapper#wrap(javax.microedition.khronos.opengles.GL)} method is called - * whenever a surface is created. A GLWrapper can be used to wrap - * the GL object that's passed to the renderer. Wrapping a GL - * object enables examining and modifying the behavior of the - * GL calls made by the renderer. - *

- * Wrapping is typically used for debugging purposes. - *

- * The default value is null. - * @param glWrapper the new GLWrapper - */ - public void setGLWrapper(GLWrapper glWrapper) { - mGLWrapper = glWrapper; - } - - /** - * Set the debug flags to a new value. The value is - * constructed by OR-together zero or more - * of the DEBUG_CHECK_* constants. The debug flags take effect - * whenever a surface is created. The default value is zero. - * @param debugFlags the new debug flags - * @see #DEBUG_CHECK_GL_ERROR - * @see #DEBUG_LOG_GL_CALLS - */ - public void setDebugFlags(int debugFlags) { - mDebugFlags = debugFlags; - } - - /** - * Get the current value of the debug flags. - * @return the current value of the debug flags. - */ - public int getDebugFlags() { - return mDebugFlags; - } - - /** - * Control whether the EGL context is preserved when the GLTextureView is paused and - * resumed. - *

- * If set to true, then the EGL context may be preserved when the GLTextureView is paused. - * Whether the EGL context is actually preserved or not depends upon whether the - * Android device that the program is running on can support an arbitrary number of EGL - * contexts or not. Devices that can only support a limited number of EGL contexts must - * release the EGL context in order to allow multiple applications to share the GPU. - *

- * If set to false, the EGL context will be released when the GLTextureView is paused, - * and recreated when the GLTextureView is resumed. - *

- * - * The default is false. - * - * @param preserveOnPause preserve the EGL context when paused - */ - public void setPreserveEGLContextOnPause(boolean preserveOnPause) { - mPreserveEGLContextOnPause = preserveOnPause; - } - - /** - * @return true if the EGL context will be preserved when paused - */ - public boolean getPreserveEGLContextOnPause() { - return mPreserveEGLContextOnPause; - } - - /** - * Set the renderer associated with this view. Also starts the thread that - * will call the renderer, which in turn causes the rendering to start. - *

This method should be called once and only once in the life-cycle of - * a GLTextureView. - *

The following GLTextureView methods can only be called before - * setRenderer is called: - *

    - *
  • {@link #setEGLConfigChooser(boolean)} - *
  • {@link #setEGLConfigChooser(EGLConfigChooser)} - *
  • {@link #setEGLConfigChooser(int, int, int, int, int, int)} - *
- *

- * The following GLTextureView methods can only be called after - * setRenderer is called: - *

    - *
  • {@link #getRenderMode()} - *
  • {@link #onPause()} - *
  • {@link #onResume()} - *
  • {@link #queueEvent(Runnable)} - *
  • {@link #requestRender()} - *
  • {@link #setRenderMode(int)} - *
- * - * @param renderer the renderer to use to perform OpenGL drawing. - */ - public void setRenderer(Renderer renderer) { - checkRenderThreadState(); - if (mEGLConfigChooser == null) { - mEGLConfigChooser = new SimpleEGLConfigChooser(true); - } - if (mEGLContextFactory == null) { - mEGLContextFactory = new DefaultContextFactory(); - } - if (mEGLWindowSurfaceFactory == null) { - mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); - } - mRenderer = renderer; - mGLThread = new GLThread(mThisWeakRef); - mGLThread.start(); - } - - /** - * Install a custom EGLContextFactory. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If this method is not called, then by default - * a context will be created with no shared context and - * with a null attribute list. - */ - public void setEGLContextFactory(EGLContextFactory factory) { - checkRenderThreadState(); - mEGLContextFactory = factory; - } - - /** - * Install a custom EGLWindowSurfaceFactory. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If this method is not called, then by default - * a window surface will be created with a null attribute list. - */ - public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { - checkRenderThreadState(); - mEGLWindowSurfaceFactory = factory; - } - - /** - * Install a custom EGLConfigChooser. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose an EGLConfig that is compatible with the current - * android.view.Surface, with a depth buffer depth of - * at least 16 bits. - * @param configChooser - */ - public void setEGLConfigChooser(EGLConfigChooser configChooser) { - checkRenderThreadState(); - mEGLConfigChooser = configChooser; - } - - /** - * Install a config chooser which will choose a config - * as close to 16-bit RGB as possible, with or without an optional depth - * buffer as close to 16-bits as possible. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose an RGB_888 surface with a depth buffer depth of - * at least 16 bits. - * - * @param needDepth - */ - public void setEGLConfigChooser(boolean needDepth) { - setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); - } - - /** - * Install a config chooser which will choose a config - * with at least the specified depthSize and stencilSize, - * and exactly the specified redSize, greenSize, blueSize and alphaSize. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose an RGB_888 surface with a depth buffer depth of - * at least 16 bits. - * - */ - public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, - blueSize, alphaSize, depthSize, stencilSize)); - } - - /** - * Inform the default EGLContextFactory and default EGLConfigChooser - * which EGLContext client version to pick. - *

Use this method to create an OpenGL ES 2.0-compatible context. - * Example: - *

-     *     public MyView(Context context) {
-     *         super(context);
-     *         setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.
-     *         setRenderer(new MyRenderer());
-     *     }
-     * 
- *

Note: Activities which require OpenGL ES 2.0 should indicate this by - * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's - * AndroidManifest.xml file. - *

If this method is called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

This method only affects the behavior of the default EGLContexFactory and the - * default EGLConfigChooser. If - * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied - * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. - * If - * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied - * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config. - * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0 - */ - public void setEGLContextClientVersion(int version) { - checkRenderThreadState(); - mEGLContextClientVersion = version; - } - - /** - * Set the rendering mode. When renderMode is - * RENDERMODE_CONTINUOUSLY, the renderer is called - * repeatedly to re-render the scene. When renderMode - * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface - * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. - *

- * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance - * by allowing the GPU and CPU to idle when the view does not need to be updated. - *

- * This method can only be called after {@link #setRenderer(Renderer)} - * - * @param renderMode one of the RENDERMODE_X constants - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - public void setRenderMode(int renderMode) { - mGLThread.setRenderMode(renderMode); - } - - /** - * Get the current rendering mode. May be called - * from any thread. Must not be called before a renderer has been set. - * @return the current rendering mode. - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - public int getRenderMode() { - return mGLThread.getRenderMode(); - } - - /** - * Request that the renderer render a frame. - * This method is typically used when the render mode has been set to - * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. - * May be called - * from any thread. Must not be called before a renderer has been set. - */ - public void requestRender() { - mGLThread.requestRender(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLTextureView. - */ - public void surfaceCreated(SurfaceTexture texture) { - mGLThread.surfaceCreated(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLTextureView. - */ - public void surfaceDestroyed(SurfaceTexture texture) { - // Surface will be destroyed when we return - mGLThread.surfaceDestroyed(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLTextureView. - */ - public void surfaceChanged(SurfaceTexture texture, int format, int w, int h) { - mGLThread.onWindowResize(w, h); - } - - /** - * Inform the view that the activity is paused. The owner of this view must - * call this method when the activity is paused. Calling this method will - * pause the rendering thread. - * Must not be called before a renderer has been set. - */ - public void onPause() { - mGLThread.onPause(); - } - - /** - * Inform the view that the activity is resumed. The owner of this view must - * call this method when the activity is resumed. Calling this method will - * recreate the OpenGL display and resume the rendering - * thread. - * Must not be called before a renderer has been set. - */ - public void onResume() { - mGLThread.onResume(); - } - - /** - * Queue a runnable to be run on the GL rendering thread. This can be used - * to communicate with the Renderer on the rendering thread. - * Must not be called before a renderer has been set. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - mGLThread.queueEvent(r); - } - - /** - * This method is used as part of the View class and is not normally - * called or subclassed by clients of GLTextureView. - */ - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (LOG_ATTACH_DETACH) { - Log.d(TAG, "onAttachedToWindow reattach =" + mDetached); - } - if (mDetached && (mRenderer != null)) { - int renderMode = RENDERMODE_CONTINUOUSLY; - if (mGLThread != null) { - renderMode = mGLThread.getRenderMode(); - } - mGLThread = new GLThread(mThisWeakRef); - if (renderMode != RENDERMODE_CONTINUOUSLY) { - mGLThread.setRenderMode(renderMode); - } - mGLThread.start(); - } - mDetached = false; - } - - /** - * This method is used as part of the View class and is not normally - * called or subclassed by clients of GLTextureView. - * Must not be called before a renderer has been set. - */ - @Override - protected void onDetachedFromWindow() { - if (LOG_ATTACH_DETACH) { - Log.d(TAG, "onDetachedFromWindow"); - } - if (mGLThread != null) { - mGLThread.requestExitAndWait(); - } - mDetached = true; - super.onDetachedFromWindow(); - } - - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - surfaceChanged(getSurfaceTexture(), 0, right - left, bottom - top); - } - - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - surfaceCreated(surface); - surfaceChanged(surface, 0, width, height); - } - - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - surfaceChanged(surface, 0, width, height); - } - - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - // MOD: Code replaced: -/* - surfaceDestroyed(surface); - return true; -*/ - // MOD: Replaced to: - if (sGLThreadManager.shouldTerminateEGLWhenPausing() && !mPreserveEGLContextOnPause) { - surfaceDestroyed(surface); - return true; - } - return false; - } - - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - requestRender(); - } - - // ---------------------------------------------------------------------- - - /** - * An interface used to wrap a GL interface. - *

Typically - * used for implementing debugging and tracing on top of the default - * GL interface. You would typically use this by creating your own class - * that implemented all the GL methods by delegating to another GL instance. - * Then you could add your own behavior before or after calling the - * delegate. All the GLWrapper would do was instantiate and return the - * wrapper GL instance: - *

-     * class MyGLWrapper implements GLWrapper {
-     *     GL wrap(GL gl) {
-     *         return new MyGLImplementation(gl);
-     *     }
-     *     static class MyGLImplementation implements GL,GL10,GL11,... {
-     *         ...
-     *     }
-     * }
-     * 
- * @see #setGLWrapper(GLWrapper) - */ - public interface GLWrapper { - /** - * Wraps a gl interface in another gl interface. - * @param gl a GL interface that is to be wrapped. - * @return either the input argument or another GL object that wraps the input argument. - */ - GL wrap(GL gl); - } - - /** - * A generic renderer interface. - *

- * The renderer is responsible for making OpenGL calls to render a frame. - *

- * GLTextureView clients typically create their own classes that implement - * this interface, and then call {@link GLTextureView#setRenderer} to - * register the renderer with the GLTextureView. - *

- * - *

- *

Developer Guides

- *

For more information about how to use OpenGL, read the - * OpenGL developer guide.

- *
- * - *

Threading

- * The renderer will be called on a separate thread, so that rendering - * performance is decoupled from the UI thread. Clients typically need to - * communicate with the renderer from the UI thread, because that's where - * input events are received. Clients can communicate using any of the - * standard Java techniques for cross-thread communication, or they can - * use the {@link GLTextureView#queueEvent(Runnable)} convenience method. - *

- *

EGL Context Lost

- * There are situations where the EGL rendering context will be lost. This - * typically happens when device wakes up after going to sleep. When - * the EGL context is lost, all OpenGL resources (such as textures) that are - * associated with that context will be automatically deleted. In order to - * keep rendering correctly, a renderer must recreate any lost resources - * that it still needs. The {@link #onSurfaceCreated(javax.microedition.khronos.opengles.GL10, javax.microedition.khronos.egl.EGLConfig)} method - * is a convenient place to do this. - * - * - * @see #setRenderer(Renderer) - */ - public interface Renderer { - /** - * Called when the surface is created or recreated. - *

- * Called when the rendering thread - * starts and whenever the EGL context is lost. The EGL context will typically - * be lost when the Android device awakes after going to sleep. - *

- * Since this method is called at the beginning of rendering, as well as - * every time the EGL context is lost, this method is a convenient place to put - * code to create resources that need to be created when the rendering - * starts, and that need to be recreated when the EGL context is lost. - * Textures are an example of a resource that you might want to create - * here. - *

- * Note that when the EGL context is lost, all OpenGL resources associated - * with that context will be automatically deleted. You do not need to call - * the corresponding "glDelete" methods such as glDeleteTextures to - * manually delete these lost resources. - *

- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param config the EGLConfig of the created surface. Can be used - * to create matching pbuffers. - */ - void onSurfaceCreated(GL10 gl, EGLConfig config); - - /** - * Called when the surface changed size. - *

- * Called after the surface is created and whenever - * the OpenGL ES surface size changes. - *

- * Typically you will set your viewport here. If your camera - * is fixed then you could also set your projection matrix here: - *

-         * void onSurfaceChanged(GL10 gl, int width, int height) {
-         *     gl.glViewport(0, 0, width, height);
-         *     // for a fixed camera, set the projection too
-         *     float ratio = (float) width / height;
-         *     gl.glMatrixMode(GL10.GL_PROJECTION);
-         *     gl.glLoadIdentity();
-         *     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
-         * }
-         * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param width - * @param height - */ - void onSurfaceChanged(GL10 gl, int width, int height); - - /** - * Called to draw the current frame. - *

- * This method is responsible for drawing the current frame. - *

- * The implementation of this method typically looks like this: - *

-         * void onDrawFrame(GL10 gl) {
-         *     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
-         *     //... other gl calls to render the scene ...
-         * }
-         * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - */ - void onDrawFrame(GL10 gl); - - void onSurfaceDestroyed(GL10 gl); - } - - /** - * An interface for customizing the eglCreateContext and eglDestroyContext calls. - *

- * This interface must be implemented by clients wishing to call - * {@link GLTextureView#setEGLContextFactory(EGLContextFactory)} - */ - public interface EGLContextFactory { - EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); - void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); - } - - private class DefaultContextFactory implements EGLContextFactory { - private int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - - public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { - int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion, - EGL10.EGL_NONE }; - - return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, - mEGLContextClientVersion != 0 ? attrib_list : null); - } - - public void destroyContext(EGL10 egl, EGLDisplay display, - EGLContext context) { - if (!egl.eglDestroyContext(display, context)) { - Log.e("DefaultContextFactory", "display:" + display + " context: " + context); - if (LOG_THREADS) { - Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId()); - } - EglHelper.throwEglException("eglDestroyContex", egl.eglGetError()); - } - } - } - - /** - * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. - *

- * This interface must be implemented by clients wishing to call - * {@link GLTextureView#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} - */ - public interface EGLWindowSurfaceFactory { - /** - * @return null if the surface cannot be constructed. - */ - EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, - Object nativeWindow); - void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); - } - - private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { - - public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, - EGLConfig config, Object nativeWindow) { - EGLSurface result = null; - try { - result = egl.eglCreateWindowSurface(display, config, nativeWindow, null); - } catch (IllegalArgumentException e) { - // This exception indicates that the surface flinger surface - // is not valid. This can happen if the surface flinger surface has - // been torn down, but the application has not yet been - // notified via SurfaceHolder.Callback.surfaceDestroyed. - // In theory the application should be notified first, - // but in practice sometimes it is not. See b/4588890 - Log.e(TAG, "eglCreateWindowSurface", e); - } - return result; - } - - public void destroySurface(EGL10 egl, EGLDisplay display, - EGLSurface surface) { - egl.eglDestroySurface(display, surface); - } - } - - /** - * An interface for choosing an EGLConfig configuration from a list of - * potential configurations. - *

- * This interface must be implemented by clients wishing to call - * {@link GLTextureView#setEGLConfigChooser(EGLConfigChooser)} - */ - public interface EGLConfigChooser { - /** - * Choose a configuration from the list. Implementors typically - * implement this method by calling - * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the - * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. - * @param egl the EGL10 for the current display. - * @param display the current display. - * @return the chosen configuration. - */ - EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); - } - - private abstract class BaseConfigChooser - implements EGLConfigChooser { - public BaseConfigChooser(int[] configSpec) { - mConfigSpec = filterConfigSpec(configSpec); - } - - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - int[] num_config = new int[1]; - if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, - num_config)) { - throw new IllegalArgumentException("eglChooseConfig failed"); - } - - int numConfigs = num_config[0]; - - if (numConfigs <= 0) { - throw new IllegalArgumentException( - "No configs match configSpec"); - } - - EGLConfig[] configs = new EGLConfig[numConfigs]; - if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, - num_config)) { - throw new IllegalArgumentException("eglChooseConfig#2 failed"); - } - EGLConfig config = chooseConfig(egl, display, configs); - if (config == null) { - throw new IllegalArgumentException("No config chosen"); - } - return config; - } - - abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs); - - protected int[] mConfigSpec; - - private int[] filterConfigSpec(int[] configSpec) { - if (mEGLContextClientVersion != 2) { - return configSpec; - } - /* We know none of the subclasses define EGL_RENDERABLE_TYPE. - * And we know the configSpec is well formed. - */ - int len = configSpec.length; - int[] newConfigSpec = new int[len + 2]; - // net.kdt.pojavlaunch.SystemCrackResolver.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); - for (int i = 0; i < len; i++) { - newConfigSpec[i] = configSpec[i]; - } - newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; - newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ - newConfigSpec[len+1] = EGL10.EGL_NONE; - return newConfigSpec; - } - } - - /** - * Choose a configuration with exactly the specified r,g,b,a sizes, - * and at least the specified depth and stencil sizes. - */ - private class ComponentSizeChooser extends BaseConfigChooser { - public ComponentSizeChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - super(new int[] { - EGL10.EGL_RED_SIZE, redSize, - EGL10.EGL_GREEN_SIZE, greenSize, - EGL10.EGL_BLUE_SIZE, blueSize, - EGL10.EGL_ALPHA_SIZE, alphaSize, - EGL10.EGL_DEPTH_SIZE, depthSize, - EGL10.EGL_STENCIL_SIZE, stencilSize, - EGL10.EGL_NONE}); - mValue = new int[1]; - mRedSize = redSize; - mGreenSize = greenSize; - mBlueSize = blueSize; - mAlphaSize = alphaSize; - mDepthSize = depthSize; - mStencilSize = stencilSize; - } - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs) { - for (EGLConfig config : configs) { - int d = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); - int s = findConfigAttrib(egl, display, config, - EGL10.EGL_STENCIL_SIZE, 0); - if ((d >= mDepthSize) && (s >= mStencilSize)) { - int r = findConfigAttrib(egl, display, config, - EGL10.EGL_RED_SIZE, 0); - int g = findConfigAttrib(egl, display, config, - EGL10.EGL_GREEN_SIZE, 0); - int b = findConfigAttrib(egl, display, config, - EGL10.EGL_BLUE_SIZE, 0); - int a = findConfigAttrib(egl, display, config, - EGL10.EGL_ALPHA_SIZE, 0); - if ((r == mRedSize) && (g == mGreenSize) - && (b == mBlueSize) && (a == mAlphaSize)) { - return config; - } - } - } - return null; - } - - private int findConfigAttrib(EGL10 egl, EGLDisplay display, - EGLConfig config, int attribute, int defaultValue) { - - if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { - return mValue[0]; - } - return defaultValue; - } - - private int[] mValue; - // Subclasses can adjust these values: - protected int mRedSize; - protected int mGreenSize; - protected int mBlueSize; - protected int mAlphaSize; - protected int mDepthSize; - protected int mStencilSize; - } - - /** - * This class will choose a RGB_888 surface with - * or without a depth buffer. - * - */ - private class SimpleEGLConfigChooser extends ComponentSizeChooser { - public SimpleEGLConfigChooser(boolean withDepthBuffer) { - super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0); - } - } - - /** - * An EGL helper class. - */ - - private static class EglHelper { - public EglHelper(WeakReference glSurfaceViewWeakRef) { - mGLSurfaceViewWeakRef = glSurfaceViewWeakRef; - } - - /** - * Initialize EGL for a given configuration spec. - * @param - */ - public void start() { - if (LOG_EGL) { - Log.w("EglHelper", "start() tid=" + Thread.currentThread().getId()); - } - /* - * Get an EGL instance - */ - mEgl = (EGL10) EGLContext.getEGL(); - - /* - * Get to the default display. - */ - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { - throw new RuntimeException("eglGetDisplay failed"); - } - - /* - * We can now initialize EGL for that display - */ - int[] version = new int[2]; - if(!mEgl.eglInitialize(mEglDisplay, version)) { - throw new RuntimeException("eglInitialize failed"); - } - GLTextureView view = mGLSurfaceViewWeakRef.get(); - if (view == null) { - mEglConfig = null; - mEglContext = null; - } else { - mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); - - /* - * Create an EGL context. We want to do this as rarely as we can, because an - * EGL context is a somewhat heavy object. - */ - mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); - } - if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { - mEglContext = null; - throwEglException("createContext"); - } - if (LOG_EGL) { - Log.w("EglHelper", "createContext " + mEglContext + " tid=" + Thread.currentThread().getId()); - } - - mEglSurface = null; - } - - /** - * Create an egl surface for the current SurfaceHolder surface. If a surface - * already exists, destroy it before creating the new surface. - * - * @return true if the surface was created successfully. - */ - public boolean createSurface() { - if (LOG_EGL) { - Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId()); - } - /* - * Check preconditions. - */ - if (mEgl == null) { - throw new RuntimeException("egl not initialized"); - } - if (mEglDisplay == null) { - throw new RuntimeException("eglDisplay not initialized"); - } - if (mEglConfig == null) { - throw new RuntimeException("mEglConfig not initialized"); - } - - /* - * The window size has changed, so we need to create a new - * surface. - */ - destroySurfaceImp(); - - /* - * Create an EGL surface we can render into. - */ - GLTextureView view = mGLSurfaceViewWeakRef.get(); - if (view != null) { - mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl, - mEglDisplay, mEglConfig, view.getSurfaceTexture()); - } else { - mEglSurface = null; - } - - if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { - int error = mEgl.eglGetError(); - if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { - Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); - } - return false; - } - - /* - * Before we can issue GL commands, we need to make sure - * the context is current and bound to a surface. - */ - if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { - /* - * Could not make the context current, probably because the underlying - * SurfaceView surface has been destroyed. - */ - logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError()); - return false; - } - - return true; - } - - /** - * Create a GL object for the current EGL context. - * @return - */ - GL createGL() { - - GL gl = mEglContext.getGL(); - GLTextureView view = mGLSurfaceViewWeakRef.get(); - if (view != null) { - if (view.mGLWrapper != null) { - gl = view.mGLWrapper.wrap(gl); - } - - if ((view.mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) { - int configFlags = 0; - Writer log = null; - if ((view.mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) { - configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; - } - if ((view.mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) { - log = new LogWriter(); - } - gl = GLDebugHelper.wrap(gl, configFlags, log); - } - } - return gl; - } - - /** - * Display the current render surface. - * @return the EGL error code from eglSwapBuffers. - */ - public int swap() { - if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { - return mEgl.eglGetError(); - } - return EGL10.EGL_SUCCESS; - } - - public void destroySurface() { - if (LOG_EGL) { - Log.w("EglHelper", "destroySurface() tid=" + Thread.currentThread().getId()); - } - destroySurfaceImp(); - } - - private void destroySurfaceImp() { - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_CONTEXT); - GLTextureView view = mGLSurfaceViewWeakRef.get(); - if (view != null) { - view.mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface); - } - mEglSurface = null; - } - } - - public void finish() { - if (LOG_EGL) { - Log.w("EglHelper", "finish() tid=" + Thread.currentThread().getId()); - } - if (mEglContext != null) { - GLTextureView view = mGLSurfaceViewWeakRef.get(); - if (view != null) { - view.mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); - } - mEglContext = null; - } - if (mEglDisplay != null) { - mEgl.eglTerminate(mEglDisplay); - mEglDisplay = null; - } - } - - private void throwEglException(String function) { - throwEglException(function, mEgl.eglGetError()); - } - - public static void throwEglException(String function, int error) { - String message = formatEglError(function, error); - if (LOG_THREADS) { - Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " " - + message); - } - throw new RuntimeException(message); - } - - public static void logEglErrorAsWarning(String tag, String function, int error) { - Log.w(tag, formatEglError(function, error)); - } - - public static String formatEglError(String function, int error) { - return function + " failed: " + error; - } - - private WeakReference mGLSurfaceViewWeakRef; - EGL10 mEgl; - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLConfig mEglConfig; - EGLContext mEglContext; - - } - - /** - * A generic GL Thread. Takes care of initializing EGL and GL. Delegates - * to a Renderer instance to do the actual drawing. Can be configured to - * render continuously or on request. - * - * All potentially blocking synchronization is done through the - * sGLThreadManager object. This avoids multiple-lock ordering issues. - * - */ - static class GLThread extends Thread { - GLThread(WeakReference glSurfaceViewWeakRef) { - super(); - mWidth = 0; - mHeight = 0; - mRequestRender = true; - mRenderMode = RENDERMODE_CONTINUOUSLY; - mGLSurfaceViewWeakRef = glSurfaceViewWeakRef; - } - - @Override - public void run() { - setName("GLThread " + getId()); - if (LOG_THREADS) { - Log.i("GLThread", "starting tid=" + getId()); - } - - try { - guardedRun(); - } catch (InterruptedException e) { - // fall thru and exit normally - } finally { - sGLThreadManager.threadExiting(this); - } - } - - /* - * This private method should only be called inside a - * synchronized(sGLThreadManager) block. - */ - private void stopEglSurfaceLocked() { - if (mHaveEglSurface) { - mHaveEglSurface = false; - mEglHelper.destroySurface(); - } - } - - /* - * This private method should only be called inside a - * synchronized(sGLThreadManager) block. - */ - private void stopEglContextLocked() { - if (mHaveEglContext) { - mEglHelper.finish(); - mHaveEglContext = false; - sGLThreadManager.releaseEglContextLocked(this); - } - } - private void guardedRun() throws InterruptedException { - mEglHelper = new EglHelper(mGLSurfaceViewWeakRef); - mHaveEglContext = false; - mHaveEglSurface = false; - try { - GL10 gl = null; - boolean createEglContext = false; - boolean createEglSurface = false; - boolean createGlInterface = false; - boolean lostEglContext = false; - boolean sizeChanged = false; - boolean wantRenderNotification = false; - boolean doRenderNotification = false; - boolean askedToReleaseEglContext = false; - int w = 0; - int h = 0; - Runnable event = null; - - while (true) { - synchronized (sGLThreadManager) { - while (true) { - if (mShouldExit) { - return; - } - - if (! mEventQueue.isEmpty()) { - event = mEventQueue.remove(0); - break; - } - - // Update the pause state. - boolean pausing = false; - if (mPaused != mRequestPaused) { - pausing = mRequestPaused; - mPaused = mRequestPaused; - sGLThreadManager.notifyAll(); - if (LOG_PAUSE_RESUME) { - Log.i("GLThread", "mPaused is now " + mPaused + " tid=" + getId()); - } - } - - // Do we need to give up the EGL context? - if (mShouldReleaseEglContext) { - if (LOG_SURFACE) { - Log.i("GLThread", "releasing EGL context because asked to tid=" + getId()); - } - stopEglSurfaceLocked(); - stopEglContextLocked(); - mShouldReleaseEglContext = false; - askedToReleaseEglContext = true; - } - - // Have we lost the EGL context? - if (lostEglContext) { - stopEglSurfaceLocked(); - stopEglContextLocked(); - lostEglContext = false; - } - - // When pausing, release the EGL surface: - if (pausing && mHaveEglSurface) { - if (LOG_SURFACE) { - Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); - } - stopEglSurfaceLocked(); - } - - // When pausing, optionally release the EGL Context: - if (pausing && mHaveEglContext) { - GLTextureView view = mGLSurfaceViewWeakRef.get(); - boolean preserveEglContextOnPause = view == null ? - false : view.mPreserveEGLContextOnPause; - if (!preserveEglContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) { - stopEglContextLocked(); - if (LOG_SURFACE) { - Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); - } - } - } - - // When pausing, optionally terminate EGL: - if (pausing) { - if (sGLThreadManager.shouldTerminateEGLWhenPausing()) { - mEglHelper.finish(); - if (LOG_SURFACE) { - Log.i("GLThread", "terminating EGL because paused tid=" + getId()); - } - } - } - - // Have we lost the SurfaceView surface? - if ((! mHasSurface) && (! mWaitingForSurface)) { - if (LOG_SURFACE) { - Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); - } - if (mHaveEglSurface) { - stopEglSurfaceLocked(); - } - mWaitingForSurface = true; - mSurfaceIsBad = false; - sGLThreadManager.notifyAll(); - } - - // Have we acquired the surface view surface? - if (mHasSurface && mWaitingForSurface) { - if (LOG_SURFACE) { - Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); - } - mWaitingForSurface = false; - sGLThreadManager.notifyAll(); - } - - if (doRenderNotification) { - if (LOG_SURFACE) { - Log.i("GLThread", "sending render notification tid=" + getId()); - } - wantRenderNotification = false; - doRenderNotification = false; - mRenderComplete = true; - sGLThreadManager.notifyAll(); - } - - // Ready to draw? - if (readyToDraw()) { - - // If we don't have an EGL context, try to acquire one. - if (! mHaveEglContext) { - if (askedToReleaseEglContext) { - askedToReleaseEglContext = false; - } else if (sGLThreadManager.tryAcquireEglContextLocked(this)) { - try { - mEglHelper.start(); - } catch (RuntimeException t) { - sGLThreadManager.releaseEglContextLocked(this); - throw t; - } - mHaveEglContext = true; - createEglContext = true; - - sGLThreadManager.notifyAll(); - } - } - - if (mHaveEglContext && !mHaveEglSurface) { - mHaveEglSurface = true; - createEglSurface = true; - createGlInterface = true; - sizeChanged = true; - } - - if (mHaveEglSurface) { - if (mSizeChanged) { - sizeChanged = true; - w = mWidth; - h = mHeight; - wantRenderNotification = true; - if (LOG_SURFACE) { - Log.i("GLThread", - "noticing that we want render notification tid=" - + getId()); - } - - // Destroy and recreate the EGL surface. - createEglSurface = true; - - mSizeChanged = false; - } - mRequestRender = false; - sGLThreadManager.notifyAll(); - break; - } - } - - // By design, this is the only place in a GLThread thread where we wait(). - if (LOG_THREADS) { - Log.i("GLThread", "waiting tid=" + getId() - + " mHaveEglContext: " + mHaveEglContext - + " mHaveEglSurface: " + mHaveEglSurface - + " mPaused: " + mPaused - + " mHasSurface: " + mHasSurface - + " mSurfaceIsBad: " + mSurfaceIsBad - + " mWaitingForSurface: " + mWaitingForSurface - + " mWidth: " + mWidth - + " mHeight: " + mHeight - + " mRequestRender: " + mRequestRender - + " mRenderMode: " + mRenderMode); - } - sGLThreadManager.wait(); - } - } // end of synchronized(sGLThreadManager) - - if (event != null) { - event.run(); - event = null; - continue; - } - - if (createEglSurface) { - if (LOG_SURFACE) { - Log.w("GLThread", "egl createSurface"); - } - if (!mEglHelper.createSurface()) { - synchronized(sGLThreadManager) { - mSurfaceIsBad = true; - sGLThreadManager.notifyAll(); - } - continue; - } - createEglSurface = false; - } - - if (createGlInterface) { - gl = (GL10) mEglHelper.createGL(); - - sGLThreadManager.checkGLDriver(gl); - createGlInterface = false; - } - - if (createEglContext) { - if (LOG_RENDERER) { - Log.w("GLThread", "onSurfaceCreated"); - } - GLTextureView view = mGLSurfaceViewWeakRef.get(); - if (view != null) { - view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); - } - createEglContext = false; - } - - if (sizeChanged) { - if (LOG_RENDERER) { - Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); - } - GLTextureView view = mGLSurfaceViewWeakRef.get(); - if (view != null) { - view.mRenderer.onSurfaceChanged(gl, w, h); - } - sizeChanged = false; - } - - if (LOG_RENDERER_DRAW_FRAME) { - Log.w("GLThread", "onDrawFrame tid=" + getId()); - } - { - GLTextureView view = mGLSurfaceViewWeakRef.get(); - if (view != null) { - view.mRenderer.onDrawFrame(gl); - } - } - int swapError = mEglHelper.swap(); - switch (swapError) { - case EGL10.EGL_SUCCESS: - break; - case EGL11.EGL_CONTEXT_LOST: - if (LOG_SURFACE) { - Log.i("GLThread", "egl context lost tid=" + getId()); - } - lostEglContext = true; - break; - default: - // Other errors typically mean that the current surface is bad, - // probably because the SurfaceView surface has been destroyed, - // but we haven't been notified yet. - // Log the error to help developers understand why rendering stopped. - EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError); - - synchronized(sGLThreadManager) { - mSurfaceIsBad = true; - sGLThreadManager.notifyAll(); - } - break; - } - - if (wantRenderNotification) { - doRenderNotification = true; - } - } - - } finally { - /* - * clean-up everything... - */ - synchronized (sGLThreadManager) { - stopEglSurfaceLocked(); - stopEglContextLocked(); - } - } - } - - public boolean ableToDraw() { - return mHaveEglContext && mHaveEglSurface && readyToDraw(); - } - - private boolean readyToDraw() { - return (!mPaused) && mHasSurface && (!mSurfaceIsBad) - && (mWidth > 0) && (mHeight > 0) - && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY)); - } - - public void setRenderMode(int renderMode) { - if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { - throw new IllegalArgumentException("renderMode"); - } - synchronized(sGLThreadManager) { - mRenderMode = renderMode; - sGLThreadManager.notifyAll(); - } - } - - public int getRenderMode() { - synchronized(sGLThreadManager) { - return mRenderMode; - } - } - - public void requestRender() { - synchronized(sGLThreadManager) { - mRequestRender = true; - sGLThreadManager.notifyAll(); - } - } - - public void surfaceCreated() { - synchronized(sGLThreadManager) { - if (LOG_THREADS) { - Log.i("GLThread", "surfaceCreated tid=" + getId()); - } - mHasSurface = true; - sGLThreadManager.notifyAll(); - while((mWaitingForSurface) && (!mExited)) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void surfaceDestroyed() { - synchronized(sGLThreadManager) { - if (LOG_THREADS) { - Log.i("GLThread", "surfaceDestroyed tid=" + getId()); - // new Throwable("Surface destroy calling at???").printStackTrace(); - } - mHasSurface = false; - sGLThreadManager.notifyAll(); - while((!mWaitingForSurface) && (!mExited)) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void onPause() { - synchronized (sGLThreadManager) { - if (LOG_PAUSE_RESUME) { - Log.i("GLThread", "onPause tid=" + getId()); - } - mRequestPaused = true; - sGLThreadManager.notifyAll(); - while ((! mExited) && (! mPaused)) { - if (LOG_PAUSE_RESUME) { - Log.i("Main thread", "onPause waiting for mPaused."); - } - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void onResume() { - synchronized (sGLThreadManager) { - if (LOG_PAUSE_RESUME) { - Log.i("GLThread", "onResume tid=" + getId()); - } - mRequestPaused = false; - mRequestRender = true; - mRenderComplete = false; - sGLThreadManager.notifyAll(); - while ((! mExited) && mPaused && (!mRenderComplete)) { - if (LOG_PAUSE_RESUME) { - Log.i("Main thread", "onResume waiting for !mPaused."); - } - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void onWindowResize(int w, int h) { - synchronized (sGLThreadManager) { - mWidth = w; - mHeight = h; - mSizeChanged = true; - mRequestRender = true; - mRenderComplete = false; - sGLThreadManager.notifyAll(); - - // Wait for thread to react to resize and render a frame - while (! mExited && !mPaused && !mRenderComplete - && ableToDraw()) { - if (LOG_SURFACE) { - Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + getId()); - } - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void requestExitAndWait() { - // don't call this from GLThread thread or it is a guaranteed - // deadlock! - synchronized(sGLThreadManager) { - mShouldExit = true; - sGLThreadManager.notifyAll(); - while (! mExited) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void requestReleaseEglContextLocked() { - mShouldReleaseEglContext = true; - sGLThreadManager.notifyAll(); - } - - /** - * Queue an "event" to be run on the GL rendering thread. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - if (r == null) { - throw new IllegalArgumentException("r must not be null"); - } - synchronized(sGLThreadManager) { - mEventQueue.add(r); - sGLThreadManager.notifyAll(); - } - } - - // Once the thread is started, all accesses to the following member - // variables are protected by the sGLThreadManager monitor - private boolean mShouldExit; - private boolean mExited; - private boolean mRequestPaused; - private boolean mPaused; - private boolean mHasSurface; - private boolean mSurfaceIsBad; - private boolean mWaitingForSurface; - private boolean mHaveEglContext; - private boolean mHaveEglSurface; - private boolean mShouldReleaseEglContext; - private int mWidth; - private int mHeight; - private int mRenderMode; - private boolean mRequestRender; - private boolean mRenderComplete; - private ArrayList mEventQueue = new ArrayList(); - private boolean mSizeChanged = true; - - // End of member variables protected by the sGLThreadManager monitor. - - private EglHelper mEglHelper; - - /** - * Set once at thread construction time, nulled out when the parent view is garbage - * called. This weak reference allows the GLTextureView to be garbage collected while - * the GLThread is still alive. - */ - private WeakReference mGLSurfaceViewWeakRef; - - } - - static class LogWriter extends Writer { - - @Override public void close() { - flushBuilder(); - } - - @Override public void flush() { - flushBuilder(); - } - - @Override public void write(char[] buf, int offset, int count) { - for(int i = 0; i < count; i++) { - char c = buf[offset + i]; - if ( c == '\n') { - flushBuilder(); - } - else { - mBuilder.append(c); - } - } - } - - private void flushBuilder() { - if (mBuilder.length() > 0) { - Log.v("GLTextureView", mBuilder.toString()); - mBuilder.delete(0, mBuilder.length()); - } - } - - private StringBuilder mBuilder = new StringBuilder(); - } - - - private void checkRenderThreadState() { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - } - - private static class GLThreadManager { - private static String TAG = "GLThreadManager"; - - public synchronized void threadExiting(GLThread thread) { - if (LOG_THREADS) { - Log.i("GLThread", "exiting tid=" + thread.getId()); - } - thread.mExited = true; - if (mEglOwner == thread) { - mEglOwner = null; - } - notifyAll(); - } - - /* - * Tries once to acquire the right to use an EGL - * context. Does not block. Requires that we are already - * in the sGLThreadManager monitor when this is called. - * - * @return true if the right to use an EGL context was acquired. - */ - public boolean tryAcquireEglContextLocked(GLThread thread) { - if (mEglOwner == thread || mEglOwner == null) { - mEglOwner = thread; - notifyAll(); - return true; - } - checkGLESVersion(); - if (mMultipleGLESContextsAllowed) { - return true; - } - // Notify the owning thread that it should release the context. - // TODO: implement a fairness policy. Currently - // if the owning thread is drawing continuously it will just - // reacquire the EGL context. - if (mEglOwner != null) { - mEglOwner.requestReleaseEglContextLocked(); - } - return false; - } - - /* - * Releases the EGL context. Requires that we are already in the - * sGLThreadManager monitor when this is called. - */ - public void releaseEglContextLocked(GLThread thread) { - if (mEglOwner == thread) { - mEglOwner = null; - } - notifyAll(); - } - - public synchronized boolean shouldReleaseEGLContextWhenPausing() { - // Release the EGL context when pausing even if - // the hardware supports multiple EGL contexts. - // Otherwise the device could run out of EGL contexts. - return mLimitedGLESContexts; - } - - public synchronized boolean shouldTerminateEGLWhenPausing() { - checkGLESVersion(); - return !mMultipleGLESContextsAllowed; - } - - public synchronized void checkGLDriver(GL10 gl) { - if (! mGLESDriverCheckComplete) { - checkGLESVersion(); - String renderer = gl.glGetString(GL10.GL_RENDERER); - if (mGLESVersion < kGLES_20) { - mMultipleGLESContextsAllowed = - ! renderer.startsWith(kMSM7K_RENDERER_PREFIX); - notifyAll(); - } - mLimitedGLESContexts = !mMultipleGLESContextsAllowed; - if (LOG_SURFACE) { - Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = " - + mMultipleGLESContextsAllowed - + " mLimitedGLESContexts = " + mLimitedGLESContexts); - } - mGLESDriverCheckComplete = true; - } - } - - private void checkGLESVersion() { - if (! mGLESVersionCheckComplete) { -// mGLESVersion = SystemProperties.getInt( -// "ro.opengles.version", -// ConfigurationInfo.GL_ES_VERSION_UNDEFINED); -// if (mGLESVersion >= kGLES_20) { -// mMultipleGLESContextsAllowed = true; -// } -// if (LOG_SURFACE) { -// Log.w(TAG, "checkGLESVersion mGLESVersion =" + -// " " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed); -// } - mGLESVersionCheckComplete = true; - } - } - - /** - * This check was required for some pre-Android-3.0 hardware. Android 3.0 provides - * support for hardware-accelerated views, therefore multiple EGL contexts are - * supported on all Android 3.0+ EGL drivers. - */ - private boolean mGLESVersionCheckComplete; - private int mGLESVersion; - private boolean mGLESDriverCheckComplete; - private boolean mMultipleGLESContextsAllowed; - private boolean mLimitedGLESContexts; - private static final int kGLES_20 = 0x20000; - private static final String kMSM7K_RENDERER_PREFIX = - "Q3Dimension MSM7500 "; - private GLThread mEglOwner; - } - - private static final GLThreadManager sGLThreadManager = new GLThreadManager(); - - private final WeakReference mThisWeakRef = - new WeakReference(this); - private GLThread mGLThread; - private Renderer mRenderer; - private boolean mDetached; - private EGLConfigChooser mEGLConfigChooser; - private EGLContextFactory mEGLContextFactory; - private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; - private GLWrapper mGLWrapper; - private int mDebugFlags; - private int mEGLContextClientVersion; - private boolean mPreserveEGLContextOnPause; -} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ImportControlActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ImportControlActivity.java index 16afb9246..15fe8abd6 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ImportControlActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ImportControlActivity.java @@ -43,7 +43,7 @@ public class ImportControlActivity extends Activity { super.onCreate(savedInstanceState); Tools.initContextConstants(getApplicationContext()); - setContentView(R.layout.import_control_layout); + setContentView(R.layout.activity_import_control); mEditText = findViewById(R.id.editText_import_control_file_name); } @@ -185,12 +185,10 @@ public class ImportControlActivity extends Activity { String jsonLayoutData = Tools.read(Tools.CTRLMAP_PATH + "/TMP_IMPORT_FILE.json"); JSONObject layoutJobj = new JSONObject(jsonLayoutData); return layoutJobj.has("version") && layoutJobj.has("mControlDataList"); - }catch (JSONException | IOException e) { e.printStackTrace(); return false; } - } public String getNameFromURI(Uri uri) { diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/InstallerTask.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/InstallerTask.java deleted file mode 100644 index 5e6b84f2c..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/InstallerTask.java +++ /dev/null @@ -1,52 +0,0 @@ -package net.kdt.pojavlaunch; -import android.os.*; - -public class InstallerTask extends AsyncTask -{ - @Override - protected String doInBackground(String[] p1) - { - try - { - downloadLibraries(p1[0]); - dexMinecraftLibs(); - downloadMinecraft(p1[0]); - dexMinecraftClient(p1[0]); - downloadAssets(p1[0]); - } - catch (Exception e) - { - return e.getMessage(); - } - return null; - } - @Override - protected void onPostExecute(String result) - { - super.onPostExecute(result); - - if(result == null){ - //No errors - } - } - private void downloadLibraries(String versionName) throws Exception - { - - } - private void dexMinecraftLibs() throws Exception - { - - } - private void downloadMinecraft(String versionName) throws Exception - { - - } - private void dexMinecraftClient(String version) throws Exception - { - - } - private void downloadAssets(String versionName) throws Exception - { - - } -} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JAssets.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JAssets.java index d05c4bce7..2f166583d 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JAssets.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JAssets.java @@ -1,9 +1,11 @@ package net.kdt.pojavlaunch; +import com.google.gson.annotations.SerializedName; + import java.util.Map; public class JAssets { - public boolean map_to_resources; + @SerializedName("map_to_resources") public boolean mapToResources; public Map objects; } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java index ca77a0e0f..c04b61906 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java @@ -1,10 +1,9 @@ package net.kdt.pojavlaunch; -import android.graphics.*; +import android.annotation.SuppressLint; import android.os.*; import android.util.*; import android.view.*; -import android.view.View.*; import android.widget.*; import java.io.*; @@ -23,169 +22,121 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc private static final int MSG_LEFT_MOUSE_BUTTON_CHECK = 1028; private AWTCanvasView mTextureView; - private LoggerView loggerView; + private LoggerView mLoggerView; - private LinearLayout touchPad; - private ImageView mousePointer; + private LinearLayout mTouchPad; + private ImageView mMousePointerImageView; private GestureDetector gestureDetector; + + private boolean mSkipDetectMod, mIsVirtualMouseEnabled; + + private int mScaleFactor; + private int[] mScaleFactors = initScaleFactors(); - private final Object mDialogLock = new Object(); - - private boolean mSkipDetectMod, isVirtualMouseEnabled; - - private int scaleFactor; - private int[] scaleFactors = initScaleFactors(); - - private final int fingerStillThreshold = 8; - private int initialX; - private int initialY; - private static boolean triggeredLeftMouseButton = false; - private Handler theHandler = new Handler() { - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_LEFT_MOUSE_BUTTON_CHECK: { - float x = CallbackBridge.mouseX; - float y = CallbackBridge.mouseY; - if (CallbackBridge.isGrabbing() && - Math.abs(initialX - x) < fingerStillThreshold && - Math.abs(initialY - y) < fingerStillThreshold) { - triggeredLeftMouseButton = true; - AWTInputBridge.sendMousePress(AWTInputEvent.BUTTON1_DOWN_MASK, true); - } - } break; - } - } - }; - + @SuppressLint("ClickableViewAccessibility") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - setContentView(R.layout.install_mod); + setContentView(R.layout.activity_java_gui_launcher); - Tools.updateWindowSize(this); Logger.getInstance().reset(); - + + mTouchPad = findViewById(R.id.main_touchpad); + mLoggerView = findViewById(R.id.launcherLoggerView); + mMousePointerImageView = findViewById(R.id.main_mouse_pointer); + mTextureView = findViewById(R.id.installmod_surfaceview); + gestureDetector = new GestureDetector(this, new SingleTapConfirm()); + mTouchPad.setFocusable(false); + mTouchPad.setVisibility(View.GONE); + + findViewById(R.id.installmod_mouse_pri).setOnTouchListener(this); + findViewById(R.id.installmod_mouse_sec).setOnTouchListener(this); + + mMousePointerImageView.post(() -> { + ViewGroup.LayoutParams params = mMousePointerImageView.getLayoutParams(); + params.width = (int) (36 / 100f * LauncherPreferences.PREF_MOUSESCALE); + params.height = (int) (54 / 100f * LauncherPreferences.PREF_MOUSESCALE); + }); + + mTouchPad.setOnTouchListener((v, event) -> { + // MotionEvent reports input details from the touch screen + // and other input controls. In this case, you are only + // interested in events where the touch position changed. + // int index = event.getActionIndex(); + int action = event.getActionMasked(); + + float x = event.getX(); + float y = event.getY(); + float prevX, prevY, mouseX, mouseY; + if(event.getHistorySize() > 0) { + prevX = event.getHistoricalX(0); + prevY = event.getHistoricalY(0); + }else{ + prevX = x; + prevY = y; + } + + mouseX = mMousePointerImageView.getX(); + mouseY = mMousePointerImageView.getY(); + + if (gestureDetector.onTouchEvent(event)) { + sendScaledMousePosition(mouseX,mouseY); + AWTInputBridge.sendMousePress(AWTInputEvent.BUTTON1_DOWN_MASK); + } else { + if (action == MotionEvent.ACTION_MOVE) { // 2 + mouseX = Math.max(0, Math.min(CallbackBridge.physicalWidth, mouseX + x - prevX)); + mouseY = Math.max(0, Math.min(CallbackBridge.physicalHeight, mouseY + y - prevY)); + placeMouseAt(mouseX, mouseY); + sendScaledMousePosition(mouseX, mouseY); + } + } + + // debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); + return true; + }); + + mTextureView.setOnTouchListener((v, event) -> { + float x = event.getX(); + float y = event.getY(); + if (gestureDetector.onTouchEvent(event)) { + sendScaledMousePosition(x, y); + AWTInputBridge.sendMousePress(AWTInputEvent.BUTTON1_DOWN_MASK); + return true; + } + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_UP: // 1 + case MotionEvent.ACTION_CANCEL: // 3 + case MotionEvent.ACTION_POINTER_UP: // 6 + break; + case MotionEvent.ACTION_MOVE: // 2 + sendScaledMousePosition(x, y); + break; + } + return true; + }); + try { JREUtils.jreReleaseList = JREUtils.readJREReleaseProperties(LauncherPreferences.PREF_DEFAULT_RUNTIME); if (JREUtils.jreReleaseList.get("JAVA_VERSION").equals("1.8.0")) { MultiRTUtils.setRuntimeNamed(this,LauncherPreferences.PREF_DEFAULT_RUNTIME); } else { - MultiRTUtils.setRuntimeNamed(this,MultiRTUtils.getExactJREName(8)); + MultiRTUtils.setRuntimeNamed(this,MultiRTUtils.getExactJreName(8)); JREUtils.jreReleaseList = JREUtils.readJREReleaseProperties(); } - - loggerView = findViewById(R.id.launcherLoggerView); - gestureDetector = new GestureDetector(this, new SingleTapConfirm()); - findViewById(R.id.installmod_mouse_pri).setOnTouchListener(this); - findViewById(R.id.installmod_mouse_sec).setOnTouchListener(this); - - this.touchPad = findViewById(R.id.main_touchpad); - touchPad.setFocusable(false); - touchPad.setVisibility(View.GONE); - - this.mousePointer = findViewById(R.id.main_mouse_pointer); - this.mousePointer.post(() -> { - ViewGroup.LayoutParams params = mousePointer.getLayoutParams(); - params.width = (int) (36 / 100f * LauncherPreferences.PREF_MOUSESCALE); - params.height = (int) (54 / 100f * LauncherPreferences.PREF_MOUSESCALE); - }); - - touchPad.setOnTouchListener(new OnTouchListener(){ - private float prevX, prevY; - @Override - public boolean onTouch(View v, MotionEvent event) { - // MotionEvent reports input details from the touch screen - // and other input controls. In this case, you are only - // interested in events where the touch position changed. - // int index = event.getActionIndex(); - - int action = event.getActionMasked(); - - float x = event.getX(); - float y = event.getY(); - if(event.getHistorySize() > 0) { - prevX = event.getHistoricalX(0); - prevY = event.getHistoricalY(0); - }else{ - prevX = x; - prevY = y; - } - float mouseX = mousePointer.getX(); - float mouseY = mousePointer.getY(); - - if (gestureDetector.onTouchEvent(event)) { - - sendScaledMousePosition(mouseX,mouseY); - - AWTInputBridge.sendMousePress(AWTInputEvent.BUTTON1_DOWN_MASK); - - - } else { - switch (action) { - case MotionEvent.ACTION_UP: // 1 - case MotionEvent.ACTION_CANCEL: // 3 - case MotionEvent.ACTION_POINTER_UP: // 6 - break; - case MotionEvent.ACTION_MOVE: // 2 - mouseX = Math.max(0, Math.min(CallbackBridge.physicalWidth, mouseX + x - prevX)); - mouseY = Math.max(0, Math.min(CallbackBridge.physicalHeight, mouseY + y - prevY)); - placeMouseAt(mouseX, mouseY); - - sendScaledMousePosition(mouseX,mouseY); - /* - if (!CallbackBridge.isGrabbing()) { - CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, isLeftMouseDown); - CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, 0, isRightMouseDown); - } - */ - break; - } - } - - // debugText.setText(CallbackBridge.DEBUG_STRING.toString()); - CallbackBridge.DEBUG_STRING.setLength(0); - - return true; - } - }); - placeMouseAt(CallbackBridge.physicalWidth / 2, CallbackBridge.physicalHeight / 2); - - // this.textLogBehindGL = (TextView) findViewById(R.id.main_log_behind_GL); - // this.textLogBehindGL.setTypeface(Typeface.MONOSPACE); final File modFile = (File) getIntent().getExtras().getSerializable("modFile"); final String javaArgs = getIntent().getExtras().getString("javaArgs"); - mTextureView = findViewById(R.id.installmod_surfaceview); - mTextureView.setOnTouchListener((v, event) -> { - float x = event.getX(); - float y = event.getY(); - if (gestureDetector.onTouchEvent(event)) { - sendScaledMousePosition(x, y); - AWTInputBridge.sendMousePress(AWTInputEvent.BUTTON1_DOWN_MASK); - return true; - } - - switch (event.getActionMasked()) { - case MotionEvent.ACTION_UP: // 1 - case MotionEvent.ACTION_CANCEL: // 3 - case MotionEvent.ACTION_POINTER_UP: // 6 - break; - case MotionEvent.ACTION_MOVE: // 2 - sendScaledMousePosition(x, y); - break; - } - return true; - }); - mSkipDetectMod = getIntent().getExtras().getBoolean("skipDetectMod", false); if (mSkipDetectMod) { new Thread(() -> launchJavaRuntime(modFile, javaArgs), "JREMainThread").start(); return; } + // No skip detection openLogOutput(null); new Thread(() -> { @@ -209,6 +160,14 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc } } + @Override + public void onResume() { + super.onResume(); + final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + final View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility(uiOptions); + } + @Override public boolean onTouch(View v, MotionEvent e) { boolean isDown; @@ -239,18 +198,18 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc } public void placeMouseAdd(float x, float y) { - this.mousePointer.setX(mousePointer.getX() + x); - this.mousePointer.setY(mousePointer.getY() + y); + mMousePointerImageView.setX(mMousePointerImageView.getX() + x); + mMousePointerImageView.setY(mMousePointerImageView.getY() + y); } public void placeMouseAt(float x, float y) { - this.mousePointer.setX(x); - this.mousePointer.setY(y); + mMousePointerImageView.setX(x); + mMousePointerImageView.setY(y); } void sendScaledMousePosition(float x, float y){ - AWTInputBridge.sendMousePos((int) map(x,0,CallbackBridge.physicalWidth, scaleFactors[0], scaleFactors[2]), - (int) map(y,0,CallbackBridge.physicalHeight, scaleFactors[1], scaleFactors[3])); + AWTInputBridge.sendMousePos((int) map(x,0,CallbackBridge.physicalWidth, mScaleFactors[0], mScaleFactors[2]), + (int) map(y,0,CallbackBridge.physicalHeight, mScaleFactors[1], mScaleFactors[3])); } public void forceClose(View v) { @@ -258,32 +217,27 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc } public void openLogOutput(View v) { - loggerView.setVisibility(View.VISIBLE); + mLoggerView.setVisibility(View.VISIBLE); } public void closeLogOutput(View view) { if (mSkipDetectMod) { - loggerView.setVisibility(View.GONE); + mLoggerView.setVisibility(View.GONE); } else { forceClose(null); } } public void toggleVirtualMouse(View v) { - isVirtualMouseEnabled = !isVirtualMouseEnabled; - touchPad.setVisibility(isVirtualMouseEnabled ? View.VISIBLE : View.GONE); + mIsVirtualMouseEnabled = !mIsVirtualMouseEnabled; + mTouchPad.setVisibility(mIsVirtualMouseEnabled ? View.VISIBLE : View.GONE); Toast.makeText(this, - isVirtualMouseEnabled ? R.string.control_mouseon : R.string.control_mouseoff, + mIsVirtualMouseEnabled ? R.string.control_mouseon : R.string.control_mouseoff, Toast.LENGTH_SHORT).show(); } - - private int doCustomInstall(File modFile, String javaArgs) throws IOException { - mSkipDetectMod = true; - return launchJavaRuntime(modFile, javaArgs); - } public int launchJavaRuntime(File modFile, String javaArgs) { - JREUtils.redirectAndPrintJRELog(this); + JREUtils.redirectAndPrintJRELog(); try { List javaArgList = new ArrayList(); @@ -313,13 +267,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc } } - @Override - public void onResume() { - super.onResume(); - final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - final View decorView = getWindow().getDecorView(); - decorView.setSystemUiVisibility(uiOptions); - } + int[] initScaleFactors(){ return initScaleFactors(true); @@ -330,37 +278,42 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc if(autoScale) { //Auto scale int minDimension = Math.min(CallbackBridge.physicalHeight, CallbackBridge.physicalWidth); - scaleFactor = Math.max(((3 * minDimension) / 1080) - 1, 1); + mScaleFactor = Math.max(((3 * minDimension) / 1080) - 1, 1); } int[] scales = new int[4]; //Left, Top, Right, Bottom scales[0] = (CallbackBridge.physicalWidth/2); - scales[0] -= scales[0]/scaleFactor; + scales[0] -= scales[0]/ mScaleFactor; scales[1] = (CallbackBridge.physicalHeight/2); - scales[1] -= scales[1]/scaleFactor; + scales[1] -= scales[1]/ mScaleFactor; scales[2] = (CallbackBridge.physicalWidth/2); - scales[2] += scales[2]/scaleFactor; + scales[2] += scales[2]/ mScaleFactor; scales[3] = (CallbackBridge.physicalHeight/2); - scales[3] += scales[3]/scaleFactor; + scales[3] += scales[3]/ mScaleFactor; return scales; } public void scaleDown(View view) { - scaleFactor = Math.max(scaleFactor - 1, 1); - scaleFactors = initScaleFactors(false); - mTextureView.initScaleFactors(scaleFactor); - sendScaledMousePosition(mousePointer.getX(),mousePointer.getY()); + mScaleFactor = Math.max(mScaleFactor - 1, 1); + mScaleFactors = initScaleFactors(false); + mTextureView.initScaleFactors(mScaleFactor); + sendScaledMousePosition(mMousePointerImageView.getX(), mMousePointerImageView.getY()); } public void scaleUp(View view) { - scaleFactor = Math.min(scaleFactor + 1, 6); - scaleFactors = initScaleFactors(false); - mTextureView.initScaleFactors(scaleFactor); - sendScaledMousePosition(mousePointer.getX(),mousePointer.getY()); + mScaleFactor = Math.min(mScaleFactor + 1, 6); + mScaleFactors = initScaleFactors(false); + mTextureView.initScaleFactors(mScaleFactor); + sendScaledMousePosition(mMousePointerImageView.getX(), mMousePointerImageView.getY()); + } + + private int doCustomInstall(File modFile, String javaArgs) throws IOException { + mSkipDetectMod = true; + return launchJavaRuntime(modFile, javaArgs); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Logger.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Logger.java index 42ef19442..d6987d9ea 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Logger.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Logger.java @@ -12,12 +12,12 @@ import java.lang.ref.WeakReference; */ @Keep public class Logger { - private static Logger loggerSingleton = null; + private static Logger sLoggerSingleton = null; /* Instance variables */ - private final File logFile; - private PrintStream logStream; - private WeakReference logListenerWeakReference = null; + private final File mLogFile; + private PrintStream mLogStream; + private WeakReference mLogListenerWeakReference = null; /* No public construction */ private Logger(){ @@ -25,25 +25,25 @@ public class Logger { } private Logger(String fileName){ - logFile = new File(Tools.DIR_GAME_HOME, fileName); + mLogFile = new File(Tools.DIR_GAME_HOME, fileName); // Make a new instance of the log file - logFile.delete(); + mLogFile.delete(); try { - logFile.createNewFile(); - logStream = new PrintStream(logFile.getAbsolutePath()); + mLogFile.createNewFile(); + mLogStream = new PrintStream(mLogFile.getAbsolutePath()); }catch (IOException e){e.printStackTrace();} } public static Logger getInstance(){ - if(loggerSingleton == null){ + if(sLoggerSingleton == null){ synchronized(Logger.class){ - if(loggerSingleton == null){ - loggerSingleton = new Logger(); + if(sLoggerSingleton == null){ + sLoggerSingleton = new Logger(); } } } - return loggerSingleton; + return sLoggerSingleton; } @@ -55,22 +55,22 @@ public class Logger { /** Print the text to the log file, no china censoring there */ public void appendToLogUnchecked(String text){ - logStream.println(text); + mLogStream.println(text); notifyLogListener(text); } /** Reset the log file, effectively erasing any previous logs */ public void reset(){ try{ - logFile.delete(); - logFile.createNewFile(); - logStream = new PrintStream(logFile.getAbsolutePath()); + mLogFile.delete(); + mLogFile.createNewFile(); + mLogStream = new PrintStream(mLogFile.getAbsolutePath()); }catch (IOException e){ e.printStackTrace();} } /** Disables the printing */ public void shutdown(){ - logStream.close(); + mLogStream.close(); } /** @@ -91,15 +91,15 @@ public class Logger { /** Link a log listener to the logger */ public void setLogListener(eventLogListener logListener){ - this.logListenerWeakReference = new WeakReference<>(logListener); + this.mLogListenerWeakReference = new WeakReference<>(logListener); } /** Notifies the event listener, if it exists */ private void notifyLogListener(String text){ - if(logListenerWeakReference == null) return; - eventLogListener logListener = logListenerWeakReference.get(); + if(mLogListenerWeakReference == null) return; + eventLogListener logListener = mLogListenerWeakReference.get(); if(logListener == null){ - logListenerWeakReference = null; + mLogListenerWeakReference = null; return; } logListener.onEventLogged(text); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/LWJGLGLFWKeycode.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/LwjglGlfwKeycode.java similarity index 97% rename from app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/LWJGLGLFWKeycode.java rename to app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/LwjglGlfwKeycode.java index 5482b01f6..fc807ef06 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/LWJGLGLFWKeycode.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/LwjglGlfwKeycode.java @@ -30,8 +30,7 @@ package net.kdt.pojavlaunch; -public class LWJGLGLFWKeycode -{ +public class LwjglGlfwKeycode { /** The unknown key. */ public static final short GLFW_KEY_UNKNOWN = 0; // should be -1 @@ -195,5 +194,8 @@ public class LWJGLGLFWKeycode GLFW_MOUSE_BUTTON_LEFT = GLFW_MOUSE_BUTTON_1, GLFW_MOUSE_BUTTON_RIGHT = GLFW_MOUSE_BUTTON_2, GLFW_MOUSE_BUTTON_MIDDLE = GLFW_MOUSE_BUTTON_3; - + + public static final int + GLFW_VISIBLE = 0x20004, + GLFW_HOVERED = 0x2000B; } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java index d9e9e2641..69c8fbd27 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java @@ -5,8 +5,6 @@ import android.content.Intent; import android.os.*; -import androidx.annotation.Nullable; - import net.kdt.pojavlaunch.customcontrols.*; import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.utils.MCOptionUtils; @@ -15,7 +13,6 @@ import java.io.*; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.DEFAULT_PREF; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_SUSTAINED_PERFORMANCE; -import static net.kdt.pojavlaunch.utils.MCOptionUtils.getMcScale; public class MainActivity extends BaseMainActivity { public static ControlLayout mControlLayout; @@ -25,7 +22,7 @@ public class MainActivity extends BaseMainActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - initLayout(R.layout.main_with_customctrl); + initLayout(R.layout.activity_basemain); // Set the sustained performance mode for available APIs if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLView.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLView.java index ddcc65c13..cecdefe96 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLView.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLView.java @@ -11,20 +11,17 @@ import static org.lwjgl.glfw.CallbackBridge.windowWidth; import android.app.Activity; import android.content.*; import android.graphics.SurfaceTexture; -import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.*; import android.view.*; import android.widget.TextView; -import android.widget.Toast; import androidx.annotation.RequiresApi; import com.google.android.material.math.MathUtils; -import net.kdt.pojavlaunch.customcontrols.TouchCharInput; import net.kdt.pojavlaunch.customcontrols.gamepad.Gamepad; import net.kdt.pojavlaunch.prefs.LauncherPreferences; import net.kdt.pojavlaunch.utils.JREUtils; @@ -36,44 +33,6 @@ import org.lwjgl.glfw.CallbackBridge; * Class dealing with showing minecraft surface and taking inputs to dispatch them to minecraft */ public class MinecraftGLView extends TextureView { - /* Gamepad object for gamepad inputs, instantiated on need */ - private Gamepad gamepad = null; - /* Pointer Debug textview, used to show info about the pointer state */ - private TextView pointerDebugText; - /* Resolution scaler option, allow downsizing a window */ - private final float scaleFactor = LauncherPreferences.DEFAULT_PREF.getInt("resolutionRatio",100)/100f; - /* Display properties, such as resolution and DPI */ - private final DisplayMetrics displayMetrics = Tools.getDisplayMetrics((Activity) getContext()); - /* Sensitivity, adjusted according to screen size */ - private final double sensitivityFactor = (1.4 * (1080f/ displayMetrics.heightPixels)); - /* Use to detect simple and double taps */ - private final TapDetector singleTapDetector = new TapDetector(1, TapDetector.DETECTION_METHOD_BOTH); - private final TapDetector doubleTapDetector = new TapDetector(2, TapDetector.DETECTION_METHOD_DOWN); - /* MC GUI scale, listened by MCOptionUtils */ - private int GUIScale = getMcScale(); - private MCOptionUtils.MCOptionListener GUIScaleListener = () -> GUIScale = getMcScale(); - /* Surface ready listener, used by the activity to launch minecraft */ - SurfaceReadyListener surfaceReadyListener = null; - - /* List of hotbarKeys, used when clicking on the hotbar */ - private static final int[] hotbarKeys = { - LWJGLGLFWKeycode.GLFW_KEY_1, LWJGLGLFWKeycode.GLFW_KEY_2, LWJGLGLFWKeycode.GLFW_KEY_3, - LWJGLGLFWKeycode.GLFW_KEY_4, LWJGLGLFWKeycode.GLFW_KEY_5, LWJGLGLFWKeycode.GLFW_KEY_6, - LWJGLGLFWKeycode.GLFW_KEY_7, LWJGLGLFWKeycode.GLFW_KEY_8, LWJGLGLFWKeycode.GLFW_KEY_9}; - /* Last hotbar button (0-9) registered */ - private int lastHotbarKey = -1; - /* Events can start with only a move instead of an pointerDown due to mouse passthrough */ - private boolean shouldBeDown = false; - /* When fingers are really near to each other, it tends to either swap or remove a pointer ! */ - private int lastPointerCount = 0; - /* Previous MotionEvent position, not scale */ - private float prevX, prevY; - /* PointerID used for the moving camera */ - private int currentPointerID = -1000; - /* Initial first pointer positions non-scaled, used to test touch sloppiness */ - private float initialX, initialY; - /* Last first pointer positions non-scaled, used to scroll distance */ - private float scrollLastInitialX, scrollLastInitialY; /* How much distance a finger has to go for touch sloppiness to be disabled */ public static final int FINGER_STILL_THRESHOLD = (int) Tools.dpToPx(9); /* How much distance a finger has to go to scroll */ @@ -81,6 +40,46 @@ public class MinecraftGLView extends TextureView { /* Handle hotbar throw button and mouse mining button */ public static final int MSG_LEFT_MOUSE_BUTTON_CHECK = 1028; public static final int MSG_DROP_ITEM_BUTTON_CHECK = 1029; + + /* Gamepad object for gamepad inputs, instantiated on need */ + private Gamepad mGamepad = null; + /* Pointer Debug textview, used to show info about the pointer state */ + private TextView mPointerDebugTextView; + /* Resolution scaler option, allow downsizing a window */ + private final float mScaleFactor = LauncherPreferences.DEFAULT_PREF.getInt("resolutionRatio",100)/100f; + /* Display properties, such as resolution and DPI */ + private final DisplayMetrics mDisplayMetrics = Tools.getDisplayMetrics((Activity) getContext()); + /* Sensitivity, adjusted according to screen size */ + private final double mSensitivityFactor = (1.4 * (1080f/ mDisplayMetrics.heightPixels)); + /* Use to detect simple and double taps */ + private final TapDetector mSingleTapDetector = new TapDetector(1, TapDetector.DETECTION_METHOD_BOTH); + private final TapDetector mDoubleTapDetector = new TapDetector(2, TapDetector.DETECTION_METHOD_DOWN); + /* MC GUI scale, listened by MCOptionUtils */ + private int mGuiScale = getMcScale(); + private MCOptionUtils.MCOptionListener mGuiScaleListener = () -> mGuiScale = getMcScale(); + /* Surface ready listener, used by the activity to launch minecraft */ + SurfaceReadyListener mSurfaceReadyListener = null; + + /* List of hotbarKeys, used when clicking on the hotbar */ + private static final int[] sHotbarKeys = { + LwjglGlfwKeycode.GLFW_KEY_1, LwjglGlfwKeycode.GLFW_KEY_2, LwjglGlfwKeycode.GLFW_KEY_3, + LwjglGlfwKeycode.GLFW_KEY_4, LwjglGlfwKeycode.GLFW_KEY_5, LwjglGlfwKeycode.GLFW_KEY_6, + LwjglGlfwKeycode.GLFW_KEY_7, LwjglGlfwKeycode.GLFW_KEY_8, LwjglGlfwKeycode.GLFW_KEY_9}; + /* Last hotbar button (0-9) registered */ + private int mLastHotbarKey = -1; + /* Events can start with only a move instead of an pointerDown due to mouse passthrough */ + private boolean mShouldBeDown = false; + /* When fingers are really near to each other, it tends to either swap or remove a pointer ! */ + private int mLastPointerCount = 0; + /* Previous MotionEvent position, not scale */ + private float mPrevX, mPrevY; + /* PointerID used for the moving camera */ + private int mCurrentPointerID = -1000; + /* Initial first pointer positions non-scaled, used to test touch sloppiness */ + private float mInitialX, mInitialY; + /* Last first pointer positions non-scaled, used to scroll distance */ + private float mScrollLastInitialX, mScrollLastInitialY; + /* Handle hotbar throw button and mouse mining button */ private final Handler theHandler = new Handler(Looper.getMainLooper()) { public void handleMessage(Message msg) { if(msg.what == MSG_LEFT_MOUSE_BUTTON_CHECK) { @@ -88,15 +87,15 @@ public class MinecraftGLView extends TextureView { float x = CallbackBridge.mouseX; float y = CallbackBridge.mouseY; if (CallbackBridge.isGrabbing() && - MathUtils.dist(x, y, initialX, initialY) < FINGER_STILL_THRESHOLD) { - triggeredLeftMouseButton = true; - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); + MathUtils.dist(x, y, mInitialX, mInitialY) < FINGER_STILL_THRESHOLD) { + mTriggeredLeftMouseButton = true; + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, true); } return; } if(msg.what == MSG_DROP_ITEM_BUTTON_CHECK) { if(CallbackBridge.isGrabbing()){ - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q); + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_Q); theHandler.sendEmptyMessageDelayed(MSG_DROP_ITEM_BUTTON_CHECK, 600); } return; @@ -105,7 +104,9 @@ public class MinecraftGLView extends TextureView { } }; /* Whether the button was triggered, used by the handler */ - private static boolean triggeredLeftMouseButton = false; + private boolean mTriggeredLeftMouseButton = false; + /* Whether the pointer debug has failed at some point */ + private boolean debugErrored = false; public MinecraftGLView(Context context) { @@ -119,68 +120,7 @@ public class MinecraftGLView extends TextureView { setOpaque(false); setFocusable(true); - MCOptionUtils.addMCOptionListener(GUIScaleListener); - } - - /** Initialize the view and all its settings */ - public void start(){ - // Add the pointer debug textview - pointerDebugText = new TextView(getContext()); - pointerDebugText.setX(0); - pointerDebugText.setY(0); - pointerDebugText.setVisibility(GONE); - ((ViewGroup)getParent()).addView(pointerDebugText); - - setSurfaceTextureListener(new SurfaceTextureListener() { - private boolean isCalled = false; - @Override - public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { - windowWidth = Tools.getDisplayFriendlyRes(width, scaleFactor); - windowHeight = Tools.getDisplayFriendlyRes(height, scaleFactor); - texture.setDefaultBufferSize(windowWidth, windowHeight); - - //Load Minecraft options: - MCOptionUtils.load(); - MCOptionUtils.set("overrideWidth", String.valueOf(windowWidth)); - MCOptionUtils.set("overrideHeight", String.valueOf(windowHeight)); - MCOptionUtils.save(); - getMcScale(); - // Should we do that? - if(isCalled) return; - isCalled = true; - - JREUtils.setupBridgeWindow(new Surface(texture)); - - new Thread(() -> { - try { - Thread.sleep(200); - if(surfaceReadyListener != null){ - surfaceReadyListener.isReady(); - } - } catch (Throwable e) { - Tools.showError(getContext(), e, true); - } - }, "JVM Main thread").start(); - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { - return true; - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { - windowWidth = Tools.getDisplayFriendlyRes(width, scaleFactor); - windowHeight = Tools.getDisplayFriendlyRes(height, scaleFactor); - CallbackBridge.sendUpdateWindowSize(windowWidth, windowHeight); - getMcScale(); - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture texture) { - texture.setDefaultBufferSize(windowWidth, windowHeight); - } - }); + MCOptionUtils.addMCOptionListener(mGuiScaleListener); } @@ -196,7 +136,7 @@ public class MinecraftGLView extends TextureView { // Mouse found if(CallbackBridge.isGrabbing()) return false; - CallbackBridge.sendCursorPos( e.getX(i) * scaleFactor, e.getY(i) * scaleFactor); + CallbackBridge.sendCursorPos( e.getX(i) * mScaleFactor, e.getY(i) * mScaleFactor); return true; //mouse event handled successfully } @@ -205,17 +145,17 @@ public class MinecraftGLView extends TextureView { //Getting scaled position from the event /* Tells if a double tap happened [MOUSE GRAB ONLY]. Doesn't tell where though. */ if(!CallbackBridge.isGrabbing()) { - CallbackBridge.mouseX = (e.getX() * scaleFactor); - CallbackBridge.mouseY = (e.getY() * scaleFactor); + CallbackBridge.mouseX = (e.getX() * mScaleFactor); + CallbackBridge.mouseY = (e.getY() * mScaleFactor); //One android click = one MC click - if(singleTapDetector.onTouchEvent(e)){ - CallbackBridge.putMouseEventWithCoords(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, CallbackBridge.mouseX, CallbackBridge.mouseY); + if(mSingleTapDetector.onTouchEvent(e)){ + CallbackBridge.putMouseEventWithCoords(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, CallbackBridge.mouseX, CallbackBridge.mouseY); return true; } } // Check double tap state, used for the hotbar - boolean hasDoubleTapped = doubleTapDetector.onTouchEvent(e); + boolean hasDoubleTapped = mDoubleTapDetector.onTouchEvent(e); switch (e.getActionMasked()) { case MotionEvent.ACTION_MOVE: @@ -227,46 +167,46 @@ public class MinecraftGLView extends TextureView { // Touch hover if(pointerCount == 1){ CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); - prevX = e.getX(); - prevY = e.getY(); + mPrevX = e.getX(); + mPrevY = e.getY(); break; } // Scrolling feature if(LauncherPreferences.PREF_DISABLE_GESTURES) break; // The pointer count can never be 0, and it is not 1, therefore it is >= 2 - int hScroll = ((int) (e.getX() - scrollLastInitialX)) / FINGER_SCROLL_THRESHOLD; - int vScroll = ((int) (e.getY() - scrollLastInitialY)) / FINGER_SCROLL_THRESHOLD; + int hScroll = ((int) (e.getX() - mScrollLastInitialX)) / FINGER_SCROLL_THRESHOLD; + int vScroll = ((int) (e.getY() - mScrollLastInitialY)) / FINGER_SCROLL_THRESHOLD; if(vScroll != 0 || hScroll != 0){ CallbackBridge.sendScroll(hScroll, vScroll); - scrollLastInitialX = e.getX(); - scrollLastInitialY = e.getY(); + mScrollLastInitialX = e.getX(); + mScrollLastInitialY = e.getY(); } break; } // Camera movement - int pointerIndex = e.findPointerIndex(currentPointerID); + int pointerIndex = e.findPointerIndex(mCurrentPointerID); int hudKeyHandled = handleGuiBar((int)e.getX(), (int) e.getY()); // Start movement, due to new pointer or loss of pointer - if (pointerIndex == -1 || lastPointerCount != pointerCount || !shouldBeDown) { + if (pointerIndex == -1 || mLastPointerCount != pointerCount || !mShouldBeDown) { if(hudKeyHandled != -1) break; //No pointer attribution on hotbar - shouldBeDown = true; - currentPointerID = e.getPointerId(0); - prevX = e.getX(); - prevY = e.getY(); + mShouldBeDown = true; + mCurrentPointerID = e.getPointerId(0); + mPrevX = e.getX(); + mPrevY = e.getY(); break; } // Continue movement as usual if(hudKeyHandled == -1){ //No camera on hotbar - CallbackBridge.mouseX += (e.getX(pointerIndex) - prevX) * sensitivityFactor; - CallbackBridge.mouseY += (e.getY(pointerIndex) - prevY) * sensitivityFactor; + CallbackBridge.mouseX += (e.getX(pointerIndex) - mPrevX) * mSensitivityFactor; + CallbackBridge.mouseY += (e.getY(pointerIndex) - mPrevY) * mSensitivityFactor; } - prevX = e.getX(pointerIndex); - prevY = e.getY(pointerIndex); + mPrevX = e.getX(pointerIndex); + mPrevY = e.getY(pointerIndex); CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); break; @@ -278,35 +218,35 @@ public class MinecraftGLView extends TextureView { boolean isTouchInHotbar = hudKeyHandled != -1; if (isTouchInHotbar) { sendKeyPress(hudKeyHandled); - if(hasDoubleTapped && hudKeyHandled == lastHotbarKey){ + if(hasDoubleTapped && hudKeyHandled == mLastHotbarKey){ //Prevent double tapping Event on two different slots - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_F); + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_F); } theHandler.sendEmptyMessageDelayed(MSG_DROP_ITEM_BUTTON_CHECK, 350); CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); - lastHotbarKey = hudKeyHandled; + mLastHotbarKey = hudKeyHandled; break; } CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); - prevX = e.getX(); - prevY = e.getY(); + mPrevX = e.getX(); + mPrevY = e.getY(); if (CallbackBridge.isGrabbing()) { - currentPointerID = e.getPointerId(0); + mCurrentPointerID = e.getPointerId(0); // It cause hold left mouse while moving camera - initialX = CallbackBridge.mouseX; - initialY = CallbackBridge.mouseY; + mInitialX = CallbackBridge.mouseX; + mInitialY = CallbackBridge.mouseY; theHandler.sendEmptyMessageDelayed(MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); } - lastHotbarKey = hudKeyHandled; + mLastHotbarKey = hudKeyHandled; break; case MotionEvent.ACTION_UP: // 1 case MotionEvent.ACTION_CANCEL: // 3 - shouldBeDown = false; - currentPointerID = -1; + mShouldBeDown = false; + mCurrentPointerID = -1; hudKeyHandled = handleGuiBar((int)e.getX(), (int) e.getY()); isTouchInHotbar = hudKeyHandled != -1; @@ -315,49 +255,49 @@ public class MinecraftGLView extends TextureView { // Stop the dropping of items if (isTouchInHotbar) { - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, false); + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_Q, 0, false); theHandler.removeMessages(MSG_DROP_ITEM_BUTTON_CHECK); break; } // Remove the mouse left button - if(triggeredLeftMouseButton){ - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, false); - triggeredLeftMouseButton = false; + if(mTriggeredLeftMouseButton){ + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, false); + mTriggeredLeftMouseButton = false; break; } theHandler.removeMessages(MSG_LEFT_MOUSE_BUTTON_CHECK); // In case of a short click, just send a quick right click if(!LauncherPreferences.PREF_DISABLE_GESTURES && - MathUtils.dist(initialX, initialY, CallbackBridge.mouseX, CallbackBridge.mouseY) < FINGER_STILL_THRESHOLD){ - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); + MathUtils.dist(mInitialX, mInitialY, CallbackBridge.mouseX, CallbackBridge.mouseY) < FINGER_STILL_THRESHOLD){ + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); } break; case MotionEvent.ACTION_POINTER_DOWN: // 5 //TODO Hey we could have some sort of middle click detection ? - scrollLastInitialX = e.getX(); - scrollLastInitialY = e.getY(); + mScrollLastInitialX = e.getX(); + mScrollLastInitialY = e.getY(); //Checking if we are pressing the hotbar to select the item hudKeyHandled = handleGuiBar((int)e.getX(e.getPointerCount()-1), (int) e.getY(e.getPointerCount()-1)); if(hudKeyHandled != -1){ sendKeyPress(hudKeyHandled); - if(hasDoubleTapped && hudKeyHandled == lastHotbarKey){ + if(hasDoubleTapped && hudKeyHandled == mLastHotbarKey){ //Prevent double tapping Event on two different slots - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_F); + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_F); } } - lastHotbarKey = hudKeyHandled; + mLastHotbarKey = hudKeyHandled; break; } // Actualise the pointer count - lastPointerCount = e.getPointerCount(); + mLastPointerCount = e.getPointerCount(); //debugText.setText(CallbackBridge.DEBUG_STRING.toString()); CallbackBridge.DEBUG_STRING.setLength(0); @@ -374,11 +314,11 @@ public class MinecraftGLView extends TextureView { int mouseCursorIndex = -1; if(Gamepad.isGamepadEvent(event)){ - if(gamepad == null){ - gamepad = new Gamepad(this, event.getDevice()); + if(mGamepad == null){ + mGamepad = new Gamepad(this, event.getDevice()); } - gamepad.update(event); + mGamepad.update(event); return true; } @@ -397,8 +337,8 @@ public class MinecraftGLView extends TextureView { } switch(event.getActionMasked()) { case MotionEvent.ACTION_HOVER_MOVE: - CallbackBridge.mouseX = (event.getX(mouseCursorIndex) * scaleFactor); - CallbackBridge.mouseY = (event.getY(mouseCursorIndex) * scaleFactor); + CallbackBridge.mouseX = (event.getX(mouseCursorIndex) * mScaleFactor); + CallbackBridge.mouseY = (event.getY(mouseCursorIndex) * mScaleFactor); CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); //debugText.setText(CallbackBridge.DEBUG_STRING.toString()); CallbackBridge.DEBUG_STRING.setLength(0); @@ -415,20 +355,20 @@ public class MinecraftGLView extends TextureView { } } - //TODO MOVE THIS SOMEWHERE ELSE - private boolean debugErrored = false; + + /** The input event for mouse with a captured pointer */ @RequiresApi(26) @Override public boolean dispatchCapturedPointerEvent(MotionEvent e) { - CallbackBridge.mouseX += (e.getX()*scaleFactor); - CallbackBridge.mouseY += (e.getY()*scaleFactor); + CallbackBridge.mouseX += (e.getX()* mScaleFactor); + CallbackBridge.mouseY += (e.getY()* mScaleFactor); if(!CallbackBridge.isGrabbing()){ releasePointerCapture(); clearFocus(); } - if (pointerDebugText.getVisibility() == View.VISIBLE && !debugErrored) { + if (mPointerDebugTextView.getVisibility() == View.VISIBLE && !debugErrored) { StringBuilder builder = new StringBuilder(); try { builder.append("PointerCapture debug\n"); @@ -448,12 +388,12 @@ public class MinecraftGLView extends TextureView { debugErrored = true; builder.append("Error getting debug. The debug will be stopped!\n").append(Log.getStackTraceString(th)); } finally { - pointerDebugText.setText(builder.toString()); + mPointerDebugTextView.setText(builder.toString()); builder.setLength(0); } } - pointerDebugText.setText(CallbackBridge.DEBUG_STRING.toString()); + mPointerDebugTextView.setText(CallbackBridge.DEBUG_STRING.toString()); CallbackBridge.DEBUG_STRING.setLength(0); switch (e.getActionMasked()) { case MotionEvent.ACTION_MOVE: @@ -506,7 +446,7 @@ public class MinecraftGLView extends TextureView { if(eventKeycode == KeyEvent.KEYCODE_BACK){ - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, event.getAction() == KeyEvent.ACTION_DOWN); + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, event.getAction() == KeyEvent.ACTION_DOWN); return true; } } @@ -514,11 +454,11 @@ public class MinecraftGLView extends TextureView { if(Gamepad.isGamepadEvent(event)){ - if(gamepad == null){ - gamepad = new Gamepad(this, event.getDevice()); + if(mGamepad == null){ + mGamepad = new Gamepad(this, event.getDevice()); } - gamepad.update(event); + mGamepad.update(event); return true; } @@ -532,11 +472,66 @@ public class MinecraftGLView extends TextureView { return false; } - /** Get the mouse direction as a string */ - private String getMoving(float pos, boolean xOrY) { - if (pos == 0) return "STOPPED"; - if (pos > 0) return xOrY ? "RIGHT" : "DOWN"; - return xOrY ? "LEFT" : "UP"; + + /** Initialize the view and all its settings */ + public void start(){ + // Add the pointer debug textview + mPointerDebugTextView = new TextView(getContext()); + mPointerDebugTextView.setX(0); + mPointerDebugTextView.setY(0); + mPointerDebugTextView.setVisibility(GONE); + ((ViewGroup)getParent()).addView(mPointerDebugTextView); + + setSurfaceTextureListener(new SurfaceTextureListener() { + private boolean isCalled = false; + @Override + public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { + windowWidth = Tools.getDisplayFriendlyRes(width, mScaleFactor); + windowHeight = Tools.getDisplayFriendlyRes(height, mScaleFactor); + texture.setDefaultBufferSize(windowWidth, windowHeight); + + //Load Minecraft options: + MCOptionUtils.load(); + MCOptionUtils.set("overrideWidth", String.valueOf(windowWidth)); + MCOptionUtils.set("overrideHeight", String.valueOf(windowHeight)); + MCOptionUtils.save(); + getMcScale(); + // Should we do that? + if(isCalled) return; + isCalled = true; + + JREUtils.setupBridgeWindow(new Surface(texture)); + + new Thread(() -> { + try { + Thread.sleep(200); + if(mSurfaceReadyListener != null){ + mSurfaceReadyListener.isReady(); + } + } catch (Throwable e) { + Tools.showError(getContext(), e, true); + } + }, "JVM Main thread").start(); + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { + return true; + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { + windowWidth = Tools.getDisplayFriendlyRes(width, mScaleFactor); + windowHeight = Tools.getDisplayFriendlyRes(height, mScaleFactor); + CallbackBridge.sendUpdateWindowSize(windowWidth, windowHeight); + getMcScale(); + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture texture) { + texture.setDefaultBufferSize(windowWidth, windowHeight); + } + }); } /** Convert the mouse button, then send it @@ -546,13 +541,13 @@ public class MinecraftGLView extends TextureView { int glfwButton = -256; switch (button) { case MotionEvent.BUTTON_PRIMARY: - glfwButton = LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT; + glfwButton = LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT; break; case MotionEvent.BUTTON_TERTIARY: - glfwButton = LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_MIDDLE; + glfwButton = LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_MIDDLE; break; case MotionEvent.BUTTON_SECONDARY: - glfwButton = LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT; + glfwButton = LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT; break; } if(glfwButton == -256) return false; @@ -560,8 +555,6 @@ public class MinecraftGLView extends TextureView { return true; } - - /** @return the hotbar key, given the position. -1 if no key are pressed */ public int handleGuiBar(int x, int y) { if (!CallbackBridge.isGrabbing()) return -1; @@ -574,17 +567,12 @@ public class MinecraftGLView extends TextureView { int barX = (CallbackBridge.physicalWidth / 2) - (barWidth / 2); if(x < barX || x >= barX + barWidth) return -1; - return hotbarKeys[(int) net.kdt.pojavlaunch.utils.MathUtils.map(x, barX, barX + barWidth, 0, 9)]; - } - - /** Return the size, given the UI scale size */ - private int mcscale(int input) { - return (int)((GUIScale * input)/scaleFactor); + return sHotbarKeys[(int) net.kdt.pojavlaunch.utils.MathUtils.map(x, barX, barX + barWidth, 0, 9)]; } /** Toggle the pointerDebugText visibility state */ public void togglepointerDebugging() { - pointerDebugText.setVisibility(pointerDebugText.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); + mPointerDebugTextView.setVisibility(mPointerDebugTextView.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); } /** A small interface called when the listener is ready for the first time */ @@ -593,6 +581,19 @@ public class MinecraftGLView extends TextureView { } public void setSurfaceReadyListener(SurfaceReadyListener listener){ - surfaceReadyListener = listener; + mSurfaceReadyListener = listener; + } + + + /** Return the size, given the UI scale size */ + private int mcscale(int input) { + return (int)((mGuiScale * input)/ mScaleFactor); + } + + /** Get the mouse direction as a string */ + private String getMoving(float pos, boolean xOrY) { + if (pos == 0) return "STOPPED"; + if (pos > 0) return xOrY ? "RIGHT" : "DOWN"; + return xOrY ? "LEFT" : "UP"; } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftLEGLView.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftLEGLView.java new file mode 100644 index 000000000..fd532295b --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftLEGLView.java @@ -0,0 +1,604 @@ +package net.kdt.pojavlaunch; + +import static net.kdt.pojavlaunch.BaseMainActivity.touchCharInput; +import static net.kdt.pojavlaunch.utils.MCOptionUtils.getMcScale; +import static org.lwjgl.glfw.CallbackBridge.sendKeyPress; +import static org.lwjgl.glfw.CallbackBridge.sendMouseButton; +import static org.lwjgl.glfw.CallbackBridge.windowHeight; +import static org.lwjgl.glfw.CallbackBridge.windowWidth; + +import android.app.Activity; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.InputDevice; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; + +import com.google.android.material.math.MathUtils; + +import net.kdt.pojavlaunch.customcontrols.gamepad.Gamepad; +import net.kdt.pojavlaunch.prefs.LauncherPreferences; +import net.kdt.pojavlaunch.utils.JREUtils; +import net.kdt.pojavlaunch.utils.MCOptionUtils; + +import org.lwjgl.glfw.CallbackBridge; + +/** + * Class dealing with showing minecraft surface and taking inputs to dispatch them to minecraft + */ +public class MinecraftLEGLView extends SurfaceView { + /* Gamepad object for gamepad inputs, instantiated on need */ + private Gamepad gamepad = null; + /* Pointer Debug textview, used to show info about the pointer state */ + private TextView pointerDebugText; + /* Resolution scaler option, allow downsizing a window */ + private final float scaleFactor = LauncherPreferences.DEFAULT_PREF.getInt("resolutionRatio",100)/100f; + /* Display properties, such as resolution and DPI */ + private final DisplayMetrics displayMetrics = Tools.getDisplayMetrics((Activity) getContext()); + /* Sensitivity, adjusted according to screen size */ + private final double sensitivityFactor = (1.4 * (1080f/ displayMetrics.heightPixels)); + /* Use to detect simple and double taps */ + private final TapDetector singleTapDetector = new TapDetector(1, TapDetector.DETECTION_METHOD_BOTH); + private final TapDetector doubleTapDetector = new TapDetector(2, TapDetector.DETECTION_METHOD_DOWN); + /* MC GUI scale, listened by MCOptionUtils */ + private int GUIScale = getMcScale(); + private MCOptionUtils.MCOptionListener GUIScaleListener = () -> GUIScale = getMcScale(); + /* Surface ready listener, used by the activity to launch minecraft */ + SurfaceReadyListener surfaceReadyListener = null; + + /* List of hotbarKeys, used when clicking on the hotbar */ + private static final int[] hotbarKeys = { + LwjglGlfwKeycode.GLFW_KEY_1, LwjglGlfwKeycode.GLFW_KEY_2, LwjglGlfwKeycode.GLFW_KEY_3, + LwjglGlfwKeycode.GLFW_KEY_4, LwjglGlfwKeycode.GLFW_KEY_5, LwjglGlfwKeycode.GLFW_KEY_6, + LwjglGlfwKeycode.GLFW_KEY_7, LwjglGlfwKeycode.GLFW_KEY_8, LwjglGlfwKeycode.GLFW_KEY_9}; + /* Last hotbar button (0-9) registered */ + private int lastHotbarKey = -1; + /* Events can start with only a move instead of an pointerDown due to mouse passthrough */ + private boolean shouldBeDown = false; + /* When fingers are really near to each other, it tends to either swap or remove a pointer ! */ + private int lastPointerCount = 0; + /* Previous MotionEvent position, not scale */ + private float prevX, prevY; + /* PointerID used for the moving camera */ + private int currentPointerID = -1000; + /* Initial first pointer positions non-scaled, used to test touch sloppiness */ + private float initialX, initialY; + /* Last first pointer positions non-scaled, used to scroll distance */ + private float scrollLastInitialX, scrollLastInitialY; + /* How much distance a finger has to go for touch sloppiness to be disabled */ + public static final int FINGER_STILL_THRESHOLD = (int) Tools.dpToPx(9); + /* How much distance a finger has to go to scroll */ + public static final int FINGER_SCROLL_THRESHOLD = (int) Tools.dpToPx(6); + /* Handle hotbar throw button and mouse mining button */ + public static final int MSG_LEFT_MOUSE_BUTTON_CHECK = 1028; + public static final int MSG_DROP_ITEM_BUTTON_CHECK = 1029; + private final Handler theHandler = new Handler(Looper.getMainLooper()) { + public void handleMessage(Message msg) { + if(msg.what == MSG_LEFT_MOUSE_BUTTON_CHECK) { + if (LauncherPreferences.PREF_DISABLE_GESTURES) return; + float x = CallbackBridge.mouseX; + float y = CallbackBridge.mouseY; + if (CallbackBridge.isGrabbing() && + MathUtils.dist(x, y, initialX, initialY) < FINGER_STILL_THRESHOLD) { + triggeredLeftMouseButton = true; + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, true); + } + return; + } + if(msg.what == MSG_DROP_ITEM_BUTTON_CHECK) { + if(CallbackBridge.isGrabbing()){ + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_Q); + theHandler.sendEmptyMessageDelayed(MSG_DROP_ITEM_BUTTON_CHECK, 600); + } + return; + } + + } + }; + /* Whether the button was triggered, used by the handler */ + private static boolean triggeredLeftMouseButton = false; + + + public MinecraftLEGLView(Context context) { + this(context, null); + } + + public MinecraftLEGLView(Context context, AttributeSet attributeSet) { + super(context, attributeSet); + //Fixes freeform and dex mode having transparent glass, + //since it forces android to used the background color of the view/layout behind it. + //setOpaque(false); + setFocusable(true); + + MCOptionUtils.addMCOptionListener(GUIScaleListener); + } + + /** Initialize the view and all its settings */ + public void start(){ + // Add the pointer debug textview + pointerDebugText = new TextView(getContext()); + pointerDebugText.setX(0); + pointerDebugText.setY(0); + pointerDebugText.setVisibility(GONE); + ((ViewGroup)getParent()).addView(pointerDebugText); + + + getHolder().addCallback(new SurfaceHolder.Callback() { + private boolean isCalled = false; + @Override + public void surfaceCreated(@NonNull SurfaceHolder holder) { + + //Load Minecraft options: + MCOptionUtils.load(); + MCOptionUtils.set("overrideWidth", String.valueOf(windowWidth)); + MCOptionUtils.set("overrideHeight", String.valueOf(windowHeight)); + MCOptionUtils.save(); + getMcScale(); + // Should we do that? + if(isCalled) return; + isCalled = true; + + getHolder().setFixedSize(windowWidth, windowHeight); + + + JREUtils.setupBridgeWindow(getHolder().getSurface()); + + new Thread(() -> { + try { + Thread.sleep(200); + if(surfaceReadyListener != null){ + surfaceReadyListener.isReady(); + } + } catch (Throwable e) { + Tools.showError(getContext(), e, true); + } + }, "JVM Main thread").start(); + } + + @Override + public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { + windowWidth = Tools.getDisplayFriendlyRes(displayMetrics.widthPixels, scaleFactor); + windowHeight = Tools.getDisplayFriendlyRes(displayMetrics.heightPixels, scaleFactor); + CallbackBridge.sendUpdateWindowSize(windowWidth, windowHeight); + getMcScale(); + Toast.makeText(getContext(), "width: " + width, Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), "height: " + height, Toast.LENGTH_SHORT).show(); + getHolder().setFixedSize(windowWidth, windowHeight); + } + + @Override + public void surfaceDestroyed(@NonNull SurfaceHolder holder) { + + } + }); + } + + + + + /** + * The touch event for both grabbed an non-grabbed mouse state on the touch screen + * Does not cover the virtual mouse touchpad + */ + @Override + public boolean onTouchEvent(MotionEvent e) { + // Looking for a mouse to handle, won't have an effect if no mouse exists. + for (int i = 0; i < e.getPointerCount(); i++) { + if (e.getToolType(i) != MotionEvent.TOOL_TYPE_MOUSE) continue; + + // Mouse found + if(CallbackBridge.isGrabbing()) return false; + CallbackBridge.sendCursorPos( e.getX(i) * scaleFactor, e.getY(i) * scaleFactor); + return true; //mouse event handled successfully + } + + // System.out.println("Pre touch, isTouchInHotbar=" + Boolean.toString(isTouchInHotbar) + ", action=" + MotionEvent.actionToString(e.getActionMasked())); + + //Getting scaled position from the event + /* Tells if a double tap happened [MOUSE GRAB ONLY]. Doesn't tell where though. */ + if(!CallbackBridge.isGrabbing()) { + CallbackBridge.mouseX = (e.getX() * scaleFactor); + CallbackBridge.mouseY = (e.getY() * scaleFactor); + //One android click = one MC click + if(singleTapDetector.onTouchEvent(e)){ + CallbackBridge.putMouseEventWithCoords(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, CallbackBridge.mouseX, CallbackBridge.mouseY); + return true; + } + } + + // Check double tap state, used for the hotbar + boolean hasDoubleTapped = doubleTapDetector.onTouchEvent(e); + + switch (e.getActionMasked()) { + case MotionEvent.ACTION_MOVE: + int pointerCount = e.getPointerCount(); + + // In-menu interactions + if(!CallbackBridge.isGrabbing()){ + + // Touch hover + if(pointerCount == 1){ + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); + prevX = e.getX(); + prevY = e.getY(); + break; + } + + // Scrolling feature + if(LauncherPreferences.PREF_DISABLE_GESTURES) break; + // The pointer count can never be 0, and it is not 1, therefore it is >= 2 + int hScroll = ((int) (e.getX() - scrollLastInitialX)) / FINGER_SCROLL_THRESHOLD; + int vScroll = ((int) (e.getY() - scrollLastInitialY)) / FINGER_SCROLL_THRESHOLD; + + if(vScroll != 0 || hScroll != 0){ + CallbackBridge.sendScroll(hScroll, vScroll); + scrollLastInitialX = e.getX(); + scrollLastInitialY = e.getY(); + } + break; + } + + // Camera movement + int pointerIndex = e.findPointerIndex(currentPointerID); + int hudKeyHandled = handleGuiBar((int)e.getX(), (int) e.getY()); + // Start movement, due to new pointer or loss of pointer + if (pointerIndex == -1 || lastPointerCount != pointerCount || !shouldBeDown) { + if(hudKeyHandled != -1) break; //No pointer attribution on hotbar + + shouldBeDown = true; + currentPointerID = e.getPointerId(0); + prevX = e.getX(); + prevY = e.getY(); + break; + } + // Continue movement as usual + if(hudKeyHandled == -1){ //No camera on hotbar + CallbackBridge.mouseX += (e.getX(pointerIndex) - prevX) * sensitivityFactor; + CallbackBridge.mouseY += (e.getY(pointerIndex) - prevY) * sensitivityFactor; + } + + prevX = e.getX(pointerIndex); + prevY = e.getY(pointerIndex); + + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); + break; + + case MotionEvent.ACTION_DOWN: // 0 + CallbackBridge.sendPrepareGrabInitialPos(); + + hudKeyHandled = handleGuiBar((int)e.getX(), (int) e.getY()); + boolean isTouchInHotbar = hudKeyHandled != -1; + if (isTouchInHotbar) { + sendKeyPress(hudKeyHandled); + if(hasDoubleTapped && hudKeyHandled == lastHotbarKey){ + //Prevent double tapping Event on two different slots + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_F); + } + + theHandler.sendEmptyMessageDelayed(MSG_DROP_ITEM_BUTTON_CHECK, 350); + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); + lastHotbarKey = hudKeyHandled; + break; + } + + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); + prevX = e.getX(); + prevY = e.getY(); + + if (CallbackBridge.isGrabbing()) { + currentPointerID = e.getPointerId(0); + // It cause hold left mouse while moving camera + initialX = CallbackBridge.mouseX; + initialY = CallbackBridge.mouseY; + theHandler.sendEmptyMessageDelayed(MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); + } + lastHotbarKey = hudKeyHandled; + break; + + case MotionEvent.ACTION_UP: // 1 + case MotionEvent.ACTION_CANCEL: // 3 + shouldBeDown = false; + currentPointerID = -1; + + hudKeyHandled = handleGuiBar((int)e.getX(), (int) e.getY()); + isTouchInHotbar = hudKeyHandled != -1; + // We only treat in world events + if (!CallbackBridge.isGrabbing()) break; + + // Stop the dropping of items + if (isTouchInHotbar) { + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_Q, 0, false); + theHandler.removeMessages(MSG_DROP_ITEM_BUTTON_CHECK); + break; + } + + // Remove the mouse left button + if(triggeredLeftMouseButton){ + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, false); + triggeredLeftMouseButton = false; + break; + } + theHandler.removeMessages(MSG_LEFT_MOUSE_BUTTON_CHECK); + + // In case of a short click, just send a quick right click + if(!LauncherPreferences.PREF_DISABLE_GESTURES && + MathUtils.dist(initialX, initialY, CallbackBridge.mouseX, CallbackBridge.mouseY) < FINGER_STILL_THRESHOLD){ + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); + } + break; + + case MotionEvent.ACTION_POINTER_DOWN: // 5 + //TODO Hey we could have some sort of middle click detection ? + + scrollLastInitialX = e.getX(); + scrollLastInitialY = e.getY(); + //Checking if we are pressing the hotbar to select the item + hudKeyHandled = handleGuiBar((int)e.getX(e.getPointerCount()-1), (int) e.getY(e.getPointerCount()-1)); + if(hudKeyHandled != -1){ + sendKeyPress(hudKeyHandled); + if(hasDoubleTapped && hudKeyHandled == lastHotbarKey){ + //Prevent double tapping Event on two different slots + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_F); + } + } + + lastHotbarKey = hudKeyHandled; + break; + + } + + // Actualise the pointer count + lastPointerCount = e.getPointerCount(); + + //debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); + + return true; + } + + /** + * The event for mouse/joystick movements + * We don't do the gamepad right now. + */ + @Override + public boolean dispatchGenericMotionEvent(MotionEvent event) { + int mouseCursorIndex = -1; + + if(Gamepad.isGamepadEvent(event)){ + if(gamepad == null){ + gamepad = new Gamepad(this, event.getDevice()); + } + + gamepad.update(event); + return true; + } + + for(int i = 0; i < event.getPointerCount(); i++) { + if(event.getToolType(i) != MotionEvent.TOOL_TYPE_MOUSE) continue; + // Mouse found + mouseCursorIndex = i; + break; + } + if(mouseCursorIndex == -1) return false; // we cant consoom that, theres no mice! + if(CallbackBridge.isGrabbing()) { + if(BaseMainActivity.isAndroid8OrHigher()){ + requestFocus(); + requestPointerCapture(); + } + } + switch(event.getActionMasked()) { + case MotionEvent.ACTION_HOVER_MOVE: + CallbackBridge.mouseX = (event.getX(mouseCursorIndex) * scaleFactor); + CallbackBridge.mouseY = (event.getY(mouseCursorIndex) * scaleFactor); + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); + //debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); + return true; + case MotionEvent.ACTION_SCROLL: + CallbackBridge.sendScroll((double) event.getAxisValue(MotionEvent.AXIS_VSCROLL), (double) event.getAxisValue(MotionEvent.AXIS_HSCROLL)); + return true; + case MotionEvent.ACTION_BUTTON_PRESS: + return sendMouseButtonUnconverted(event.getActionButton(),true); + case MotionEvent.ACTION_BUTTON_RELEASE: + return sendMouseButtonUnconverted(event.getActionButton(),false); + default: + return false; + } + } + + //TODO MOVE THIS SOMEWHERE ELSE + private boolean debugErrored = false; + /** The input event for mouse with a captured pointer */ + @RequiresApi(26) + @Override + public boolean dispatchCapturedPointerEvent(MotionEvent e) { + CallbackBridge.mouseX += (e.getX()*scaleFactor); + CallbackBridge.mouseY += (e.getY()*scaleFactor); + if(!CallbackBridge.isGrabbing()){ + releasePointerCapture(); + clearFocus(); + } + + if (pointerDebugText.getVisibility() == View.VISIBLE && !debugErrored) { + StringBuilder builder = new StringBuilder(); + try { + builder.append("PointerCapture debug\n"); + builder.append("MotionEvent=").append(e.getActionMasked()).append("\n"); + builder.append("PressingBtn=").append(MotionEvent.class.getDeclaredMethod("buttonStateToString").invoke(null, e.getButtonState())).append("\n\n"); + + builder.append("PointerX=").append(e.getX()).append("\n"); + builder.append("PointerY=").append(e.getY()).append("\n"); + builder.append("RawX=").append(e.getRawX()).append("\n"); + builder.append("RawY=").append(e.getRawY()).append("\n\n"); + + builder.append("XPos=").append(CallbackBridge.mouseX).append("\n"); + builder.append("YPos=").append(CallbackBridge.mouseY).append("\n\n"); + builder.append("MovingX=").append(getMoving(e.getX(), true)).append("\n"); + builder.append("MovingY=").append(getMoving(e.getY(), false)).append("\n"); + } catch (Throwable th) { + debugErrored = true; + builder.append("Error getting debug. The debug will be stopped!\n").append(Log.getStackTraceString(th)); + } finally { + pointerDebugText.setText(builder.toString()); + builder.setLength(0); + } + } + + pointerDebugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); + switch (e.getActionMasked()) { + case MotionEvent.ACTION_MOVE: + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); + return true; + case MotionEvent.ACTION_BUTTON_PRESS: + return sendMouseButtonUnconverted(e.getActionButton(), true); + case MotionEvent.ACTION_BUTTON_RELEASE: + return sendMouseButtonUnconverted(e.getActionButton(), false); + case MotionEvent.ACTION_SCROLL: + CallbackBridge.sendScroll(e.getAxisValue(MotionEvent.AXIS_HSCROLL), e.getAxisValue(MotionEvent.AXIS_VSCROLL)); + return true; + default: + return false; + } + } + + /** The event for keyboard/ gamepad button inputs */ + @Override + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + //Toast.makeText(this, event.toString(),Toast.LENGTH_SHORT).show(); + //Toast.makeText(this, event.getDevice().toString(), Toast.LENGTH_SHORT).show(); + + //Filtering useless events by order of probability + if((event.getFlags() & KeyEvent.FLAG_FALLBACK) == KeyEvent.FLAG_FALLBACK) return true; + int eventKeycode = event.getKeyCode(); + if(eventKeycode == KeyEvent.KEYCODE_UNKNOWN) return true; + if(eventKeycode == KeyEvent.KEYCODE_VOLUME_DOWN) return false; + if(eventKeycode == KeyEvent.KEYCODE_VOLUME_UP) return false; + if(event.getRepeatCount() != 0) return true; + if(event.getAction() == KeyEvent.ACTION_MULTIPLE) return true; + + //Toast.makeText(this, "FIRST VERIF PASSED", Toast.LENGTH_SHORT).show(); + + //Sometimes, key events comes from SOME keys of the software keyboard + //Even weirder, is is unknown why a key or another is selected to trigger a keyEvent + if((event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) == KeyEvent.FLAG_SOFT_KEYBOARD){ + if(eventKeycode == KeyEvent.KEYCODE_ENTER) return true; //We already listen to it. + touchCharInput.dispatchKeyEvent(event); + return true; + } + //Toast.makeText(this, "SECOND VERIF PASSED", Toast.LENGTH_SHORT).show(); + + + //Sometimes, key events may come from the mouse + if(event.getDevice() != null + && ( (event.getSource() & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE + || (event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) ){ + //Toast.makeText(this, "THE EVENT COMES FROM A MOUSE", Toast.LENGTH_SHORT).show(); + + + if(eventKeycode == KeyEvent.KEYCODE_BACK){ + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, event.getAction() == KeyEvent.ACTION_DOWN); + return true; + } + } + System.out.println(event); + + if(Gamepad.isGamepadEvent(event)){ + + if(gamepad == null){ + gamepad = new Gamepad(this, event.getDevice()); + } + + gamepad.update(event); + return true; + } + + int index = EfficientAndroidLWJGLKeycode.getIndexByKey(eventKeycode); + if(index >= 0) { + //Toast.makeText(this,"THIS IS A KEYBOARD EVENT !", Toast.LENGTH_SHORT).show(); + EfficientAndroidLWJGLKeycode.execKey(event, index); + return true; + } + + return false; + } + + /** Get the mouse direction as a string */ + private String getMoving(float pos, boolean xOrY) { + if (pos == 0) return "STOPPED"; + if (pos > 0) return xOrY ? "RIGHT" : "DOWN"; + return xOrY ? "LEFT" : "UP"; + } + + /** Convert the mouse button, then send it + * @return Whether the event was processed + */ + public static boolean sendMouseButtonUnconverted(int button, boolean status) { + int glfwButton = -256; + switch (button) { + case MotionEvent.BUTTON_PRIMARY: + glfwButton = LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT; + break; + case MotionEvent.BUTTON_TERTIARY: + glfwButton = LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_MIDDLE; + break; + case MotionEvent.BUTTON_SECONDARY: + glfwButton = LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT; + break; + } + if(glfwButton == -256) return false; + sendMouseButton(glfwButton, status); + return true; + } + + + + /** @return the hotbar key, given the position. -1 if no key are pressed */ + public int handleGuiBar(int x, int y) { + if (!CallbackBridge.isGrabbing()) return -1; + + int barHeight = mcscale(20); + int barY = CallbackBridge.physicalHeight - barHeight; + if(y < barY) return -1; + + int barWidth = mcscale(180); + int barX = (CallbackBridge.physicalWidth / 2) - (barWidth / 2); + if(x < barX || x >= barX + barWidth) return -1; + + return hotbarKeys[(int) net.kdt.pojavlaunch.utils.MathUtils.map(x, barX, barX + barWidth, 0, 9)]; + } + + /** Return the size, given the UI scale size */ + private int mcscale(int input) { + return (int)((GUIScale * input)/scaleFactor); + } + + /** Toggle the pointerDebugText visibility state */ + public void togglepointerDebugging() { + pointerDebugText.setVisibility(pointerDebugText.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); + } + + /** A small interface called when the listener is ready for the first time */ + public interface SurfaceReadyListener { + void isReady(); + } + + public void setSurfaceReadyListener(SurfaceReadyListener listener){ + surfaceReadyListener = listener; + } +} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java index 8b27f901d..059e49eb8 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java @@ -14,40 +14,37 @@ import java.util.*; import net.kdt.pojavlaunch.utils.*; -public class PojavApplication extends Application -{ +public class PojavApplication extends Application { public static String CRASH_REPORT_TAG = "PojavCrashReport"; @Override public void onCreate() { - Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){ - @Override - public void uncaughtException(Thread thread, Throwable th) { - boolean storagePermAllowed = Build.VERSION.SDK_INT < 23 || ActivityCompat.checkSelfPermission(PojavApplication.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; - File crashFile = new File(storagePermAllowed ? Tools.DIR_GAME_HOME : Tools.DIR_DATA, "latestcrash.txt"); - try { - // Write to file, since some devices may not able to show error - crashFile.getParentFile().mkdirs(); - crashFile.createNewFile(); - PrintStream crashStream = new PrintStream(crashFile); - crashStream.append("PojavLauncher crash report\n"); - crashStream.append(" - Time: " + DateFormat.getDateTimeInstance().format(new Date()) + "\n"); - crashStream.append(" - Device: " + Build.PRODUCT + " " + Build.MODEL + "\n"); - crashStream.append(" - Android version: " + Build.VERSION.RELEASE + "\n"); - crashStream.append(" - Crash stack trace:\n"); - crashStream.append(" - Launcher version: " + BuildConfig.VERSION_NAME + "\n"); - crashStream.append(Log.getStackTraceString(th)); - crashStream.close(); - } catch (Throwable th2) { - Log.e(CRASH_REPORT_TAG, " - Exception attempt saving crash stack trace:", th2); - Log.e(CRASH_REPORT_TAG, " - The crash stack trace was:", th); - } - - FatalErrorActivity.showError(PojavApplication.this, crashFile.getAbsolutePath(), storagePermAllowed, th); - // android.os.Process.killProcess(android.os.Process.myPid()); - - BaseMainActivity.fullyExit(); + Thread.setDefaultUncaughtExceptionHandler((thread, th) -> { + boolean storagePermAllowed = Build.VERSION.SDK_INT < 23 || + ActivityCompat.checkSelfPermission(PojavApplication.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + File crashFile = new File(storagePermAllowed ? Tools.DIR_GAME_HOME : Tools.DIR_DATA, "latestcrash.txt"); + try { + // Write to file, since some devices may not able to show error + crashFile.getParentFile().mkdirs(); + crashFile.createNewFile(); + PrintStream crashStream = new PrintStream(crashFile); + crashStream.append("PojavLauncher crash report\n"); + crashStream.append(" - Time: " + DateFormat.getDateTimeInstance().format(new Date()) + "\n"); + crashStream.append(" - Device: " + Build.PRODUCT + " " + Build.MODEL + "\n"); + crashStream.append(" - Android version: " + Build.VERSION.RELEASE + "\n"); + crashStream.append(" - Crash stack trace:\n"); + crashStream.append(" - Launcher version: " + BuildConfig.VERSION_NAME + "\n"); + crashStream.append(Log.getStackTraceString(th)); + crashStream.close(); + } catch (Throwable throwable) { + Log.e(CRASH_REPORT_TAG, " - Exception attempt saving crash stack trace:", throwable); + Log.e(CRASH_REPORT_TAG, " - The crash stack trace was:", th); } + + FatalErrorActivity.showError(PojavApplication.this, crashFile.getAbsolutePath(), storagePermAllowed, th); + // android.os.Process.killProcess(android.os.Process.myPid()); + + BaseMainActivity.fullyExit(); }); try { @@ -70,10 +67,9 @@ public class PojavApplication extends Application .concat("/x86"); } - - } catch (Throwable th) { + } catch (Throwable throwable) { Intent ferrorIntent = new Intent(this, FatalErrorActivity.class); - ferrorIntent.putExtra("throwable", th); + ferrorIntent.putExtra("throwable", throwable); startActivity(ferrorIntent); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLauncherActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLauncherActivity.java index bb0ca9881..83f13d9ce 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLauncherActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLauncherActivity.java @@ -98,7 +98,7 @@ public class PojavLauncherActivity extends BaseLauncherActivity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.launcher_main_v4); + setContentView(R.layout.activity_pojav_launcher); //Boilerplate linking/initialisation viewPager = findViewById(R.id.launchermainTabPager); @@ -288,7 +288,7 @@ public class PojavLauncherActivity extends BaseLauncherActivity accountFaceImageView.setImageBitmap(mProfile.getSkinFace()); //TODO FULL BACKGROUND LOGIN - tvConnectStatus.setText(mProfile.accessToken.equals("0") ? R.string.mcl_account_offline : R.string.mcl_account_connected); + tvConnectStatus.setText(mProfile.accessToken.equals("0") ? R.string.mcl_account_local : R.string.mcl_account_connected); } catch(Exception e) { mProfile = new MinecraftAccount(); Tools.showError(this, e, true); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java index 4366ae75c..dd91ed26a 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java @@ -10,10 +10,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.AssetManager; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Color; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Build; @@ -22,7 +19,6 @@ import android.text.Html; import android.text.SpannableString; import android.text.Spanned; import android.text.style.StyleSpan; -import android.util.Base64; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -48,8 +44,6 @@ import androidx.core.content.ContextCompat; import net.kdt.pojavlaunch.authenticator.microsoft.MicrosoftAuthTask; import net.kdt.pojavlaunch.authenticator.microsoft.ui.MicrosoftLoginGUIActivity; import net.kdt.pojavlaunch.authenticator.mojang.InvalidateTokenTask; -import net.kdt.pojavlaunch.authenticator.mojang.LoginListener; -import net.kdt.pojavlaunch.authenticator.mojang.LoginTask; import net.kdt.pojavlaunch.authenticator.mojang.RefreshListener; import net.kdt.pojavlaunch.customcontrols.CustomControls; import net.kdt.pojavlaunch.multirt.MultiRTConfigDialog; @@ -69,15 +63,13 @@ import java.io.InputStreamReader; import java.util.Arrays; import java.util.Locale; -public class PojavLoginActivity extends BaseActivity -// MineActivity -{ +public class PojavLoginActivity extends BaseActivity { private final Object mLockStoragePerm = new Object(); private final Object mLockSelectJRE = new Object(); - private EditText edit2, edit3; + private EditText edit2; private final int REQUEST_STORAGE_REQUEST_CODE = 1; - private CheckBox sRemember, sOffline; + private CheckBox sRemember; private TextView startupTextView; private SharedPreferences firstLaunchPrefs; private MinecraftAccount mProfile = null; @@ -173,7 +165,7 @@ public class PojavLoginActivity extends BaseActivity } } private void uiInit() { - setContentView(R.layout.launcher_login_v3); + setContentView(R.layout.activity_pojav_login); Spinner spinnerChgLang = findViewById(R.id.login_spinner_language); @@ -243,15 +235,8 @@ public class PojavLoginActivity extends BaseActivity }); edit2 = (EditText) findViewById(R.id.login_edit_email); - edit3 = (EditText) findViewById(R.id.login_edit_password); sRemember = findViewById(R.id.login_switch_remember); - sOffline = findViewById(R.id.login_switch_offline); - sOffline.setOnCheckedChangeListener((p1, p2) -> { - // May delete later - edit3.setEnabled(!p2); - }); - isSkipInit = true; } @@ -496,14 +481,14 @@ public class PojavLoginActivity extends BaseActivity final Dialog accountDialog = new Dialog(PojavLoginActivity.this); - accountDialog.setContentView(R.layout.simple_account_list_holder); + accountDialog.setContentView(R.layout.dialog_select_account); LinearLayout accountListLayout = accountDialog.findViewById(R.id.accountListLayout); LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); for (int accountIndex = 0; accountIndex < accountArr.length; accountIndex++) { String s = accountArr[accountIndex]; - View child = inflater.inflate(R.layout.simple_account_list_item, accountListLayout,false); + View child = inflater.inflate(R.layout.item_minecraft_account, accountListLayout,false); TextView accountName = child.findViewById(R.id.accountitem_text_name); ImageButton removeButton = child.findViewById(R.id.accountitem_button_remove); ImageView imageView = child.findViewById(R.id.account_head); @@ -535,11 +520,9 @@ public class PojavLoginActivity extends BaseActivity }; MinecraftAccount acc = MinecraftAccount.load(selectedAccName); - if (acc.isMicrosoft){ + if (acc.accessToken.length() >= 5){ new MicrosoftAuthTask(PojavLoginActivity.this, authListener) .execute("true", acc.msaRefreshToken); - } else if (acc.accessToken.length() >= 5) { - PojavProfile.updateTokens(PojavLoginActivity.this, selectedAccName, authListener); } else { accountDialog.dismiss(); PojavProfile.launch(PojavLoginActivity.this, selectedAccName); @@ -580,7 +563,7 @@ public class PojavLoginActivity extends BaseActivity accountDialog.show(); } - private MinecraftAccount loginOffline() { + private MinecraftAccount loginLocal() { new File(Tools.DIR_ACCOUNT_OLD).mkdir(); String text = edit2.getText().toString(); @@ -590,8 +573,6 @@ public class PojavLoginActivity extends BaseActivity edit2.setError(getString(R.string.login_error_invalid_username)); } else if (new File(Tools.DIR_ACCOUNT_NEW + "/" + text + ".json").exists()) { edit2.setError(getString(R.string.login_error_exist_username)); - } else if (!edit3.getText().toString().isEmpty()) { - edit3.setError(getString(R.string.login_error_offline_password)); } else { MinecraftAccount builder = new MinecraftAccount(); builder.isMicrosoft = false; @@ -605,43 +586,8 @@ public class PojavLoginActivity extends BaseActivity public void loginMC(final View v) { - - if (sOffline.isChecked()) { - mProfile = loginOffline(); - playProfile(false); - } else { - ProgressBar prb = findViewById(R.id.launcherAccProgress); - new LoginTask().setLoginListener(new LoginListener(){ - - - @Override - public void onBeforeLogin() { - v.setEnabled(false); - prb.setVisibility(View.VISIBLE); - } - - @Override - public void onLoginDone(String[] result) { - if(result[0].equals("ERROR")){ - Tools.dialogOnUiThread(PojavLoginActivity.this, - getResources().getString(R.string.global_error), strArrToString(result)); - } else{ - MinecraftAccount builder = new MinecraftAccount(); - builder.accessToken = result[1]; - builder.clientToken = result[2]; - builder.profileId = result[3]; - builder.username = result[4]; - builder.updateSkinFace(); - mProfile = builder; - } - runOnUiThread(() -> { - v.setEnabled(true); - prb.setVisibility(View.GONE); - playProfile(false); - }); - } - }).execute(edit2.getText().toString(), edit3.getText().toString()); - } + mProfile = loginLocal(); + playProfile(false); } private void playProfile(boolean notOnLogin) { diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavMigrator.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavMigrator.java index 825f4a49c..ed4082e7b 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavMigrator.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavMigrator.java @@ -6,8 +6,7 @@ import net.kdt.pojavlaunch.value.*; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -public class PojavMigrator -{ +public class PojavMigrator { public static void migrateAccountData(Context ctx) { File oldAccDir = new File(Tools.DIR_ACCOUNT_OLD); if (oldAccDir.exists() && oldAccDir.isDirectory()) { diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavProfile.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavProfile.java index 8a6c1b339..53252682b 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavProfile.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavProfile.java @@ -8,14 +8,11 @@ import android.util.Log; import com.google.gson.JsonSyntaxException; import java.io.File; import java.io.IOException; -import net.kdt.pojavlaunch.authenticator.mojang.RefreshListener; -import net.kdt.pojavlaunch.authenticator.mojang.RefreshTokenTask; import net.kdt.pojavlaunch.value.MinecraftAccount; -public class PojavProfile -{ - private static String PROFILE_PREF = "pojav_profile"; - private static String PROFILE_PREF_FILE = "file"; +public class PojavProfile { + private static final String PROFILE_PREF = "pojav_profile"; + private static final String PROFILE_PREF_FILE = "file"; public static String PROFILE_PREF_TEMP_CONTENT = "tempContent"; public static SharedPreferences getPrefs(Context ctx) { @@ -33,26 +30,26 @@ public class PojavProfile public static MinecraftAccount getTempProfileContent() { try { - MinecraftAccount acc = MinecraftAccount.parse(Tools.read(Tools.DIR_DATA+"/cache/tempacc.json")); - if (acc.accessToken == null) { - acc.accessToken = "0"; + MinecraftAccount account = MinecraftAccount.parse(Tools.read(Tools.DIR_DATA+"/cache/tempacc.json")); + if (account.accessToken == null) { + account.accessToken = "0"; } - if (acc.clientToken == null) { - acc.clientToken = "0"; + if (account.clientToken == null) { + account.clientToken = "0"; } - if (acc.profileId == null) { - acc.profileId = "00000000-0000-0000-0000-000000000000"; + if (account.profileId == null) { + account.profileId = "00000000-0000-0000-0000-000000000000"; } - if (acc.username == null) { - acc.username = "0"; + if (account.username == null) { + account.username = "0"; } - if (acc.selectedVersion == null) { - acc.selectedVersion = "1.7.10"; + if (account.selectedVersion == null) { + account.selectedVersion = "1.7.10"; } - if (acc.msaRefreshToken == null) { - acc.msaRefreshToken = "0"; + if (account.msaRefreshToken == null) { + account.msaRefreshToken = "0"; } - return acc; + return account; }catch (IOException e) { Log.e(MinecraftAccount.class.getName(), "Caught an exception while loading the temporary profile",e); return null; @@ -104,8 +101,4 @@ public class PojavProfile Intent intent = new Intent(ctx, PojavLauncherActivity.class); //MCLauncherActivity.class); ctx.startActivity(intent); } - - public static void updateTokens(final Activity ctx, final String name, RefreshListener listen) throws Exception { - new RefreshTokenTask(ctx, listen).execute(name); - } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/SingleTapConfirm.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/SingleTapConfirm.java index bd82eb77f..ebfb922bc 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/SingleTapConfirm.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/SingleTapConfirm.java @@ -3,8 +3,7 @@ package net.kdt.pojavlaunch; import android.view.*; import android.view.GestureDetector.*; -public class SingleTapConfirm extends SimpleOnGestureListener -{ +public class SingleTapConfirm extends SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent event) { return true; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/TapDetector.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/TapDetector.java index 9aaeeeeca..a76dd6d95 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/TapDetector.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/TapDetector.java @@ -22,10 +22,10 @@ public class TapDetector { private final static int TAP_MAX_DELTA_MS = 300; private final static int TAP_SLOP_SQUARE_PX = (int) Math.pow(Tools.dpToPx(100), 2); - private final int tapNumberToDetect; - private int currentTapNumber = 0; + private final int mTapNumberToDetect; + private int mCurrentTapNumber = 0; - private final int detectionMethod; + private final int mDetectionMethod; private long mLastEventTime = 0; private float mLastX = 9999; @@ -36,9 +36,9 @@ public class TapDetector { * @param detectionMethod Method used to detect touches. See DETECTION_METHOD constants above. */ public TapDetector(int tapNumberToDetect, int detectionMethod){ - this.detectionMethod = detectionMethod; + this.mDetectionMethod = detectionMethod; //We expect both ACTION_DOWN and ACTION_UP for the DETECTION_METHOD_BOTH - this.tapNumberToDetect = detectBothTouch() ? 2*tapNumberToDetect : tapNumberToDetect; + this.mTapNumberToDetect = detectBothTouch() ? 2*tapNumberToDetect : tapNumberToDetect; } /** @@ -78,17 +78,17 @@ public class TapDetector { mLastY = eventY; //Check for high enough speed and precision - if(currentTapNumber > 0){ + if(mCurrentTapNumber > 0){ if ((deltaTime < TAP_MIN_DELTA_MS || deltaTime > TAP_MAX_DELTA_MS) || ((deltaX*deltaX + deltaY*deltaY) > TAP_SLOP_SQUARE_PX)) { // We invalidate previous taps, not this one though - currentTapNumber = 0; + mCurrentTapNumber = 0; } } //A worthy tap happened - currentTapNumber += 1; - if(currentTapNumber >= tapNumberToDetect){ + mCurrentTapNumber += 1; + if(mCurrentTapNumber >= mTapNumberToDetect){ resetTapDetectionState(); return true; } @@ -101,22 +101,21 @@ public class TapDetector { * Reset the double tap values. */ private void resetTapDetectionState(){ - currentTapNumber = 0; + mCurrentTapNumber = 0; mLastEventTime = 0; mLastX = 9999; mLastY = 9999; } - private boolean detectDownTouch(){ - return (detectionMethod & DETECTION_METHOD_DOWN) == DETECTION_METHOD_DOWN; + return (mDetectionMethod & DETECTION_METHOD_DOWN) == DETECTION_METHOD_DOWN; } private boolean detectUpTouch(){ - return (detectionMethod & DETECTION_METHOD_UP) == DETECTION_METHOD_UP; + return (mDetectionMethod & DETECTION_METHOD_UP) == DETECTION_METHOD_UP; } private boolean detectBothTouch(){ - return detectionMethod == DETECTION_METHOD_BOTH; + return mDetectionMethod == DETECTION_METHOD_BOTH; } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java index 78007b76a..c60a21e3e 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -211,7 +211,7 @@ public final class Tools { versionName = versionInfo.inheritsFrom; } - String userType = "mojang"; + String userType = "msa"; File gameDir = new File(strGameDir); gameDir.mkdirs(); @@ -449,42 +449,37 @@ public final class Tools { private static void showError(final Context ctx, final int titleId, final Throwable e, final boolean exitIfOk, final boolean showMore) { e.printStackTrace(); - Runnable runnable = new Runnable(){ - - @Override - public void run() - { - final String errMsg = showMore ? Log.getStackTraceString(e): e.getMessage(); - AlertDialog.Builder builder = new AlertDialog.Builder((Context) ctx) - .setTitle(titleId) - .setMessage(errMsg) - .setPositiveButton(android.R.string.ok, (DialogInterface.OnClickListener) (p1, p2) -> { - if(exitIfOk) { - if (ctx instanceof BaseMainActivity) { - BaseMainActivity.fullyExit(); - } else if (ctx instanceof Activity) { - ((Activity) ctx).finish(); - } + Runnable runnable = () -> { + final String errMsg = showMore ? Log.getStackTraceString(e): e.getMessage(); + AlertDialog.Builder builder = new AlertDialog.Builder((Context) ctx) + .setTitle(titleId) + .setMessage(errMsg) + .setPositiveButton(android.R.string.ok, (DialogInterface.OnClickListener) (p1, p2) -> { + if(exitIfOk) { + if (ctx instanceof BaseMainActivity) { + BaseMainActivity.fullyExit(); + } else if (ctx instanceof Activity) { + ((Activity) ctx).finish(); } - }) - .setNegativeButton(showMore ? R.string.error_show_less : R.string.error_show_more, (DialogInterface.OnClickListener) (p1, p2) -> showError(ctx, titleId, e, exitIfOk, !showMore)) - .setNeutralButton(android.R.string.copy, (DialogInterface.OnClickListener) (p1, p2) -> { - ClipboardManager mgr = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); - mgr.setPrimaryClip(ClipData.newPlainText("error", Log.getStackTraceString(e))); - if(exitIfOk) { - if (ctx instanceof BaseMainActivity) { - BaseMainActivity.fullyExit(); - } else { - ((Activity) ctx).finish(); - } + } + }) + .setNegativeButton(showMore ? R.string.error_show_less : R.string.error_show_more, (DialogInterface.OnClickListener) (p1, p2) -> showError(ctx, titleId, e, exitIfOk, !showMore)) + .setNeutralButton(android.R.string.copy, (DialogInterface.OnClickListener) (p1, p2) -> { + ClipboardManager mgr = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); + mgr.setPrimaryClip(ClipData.newPlainText("error", Log.getStackTraceString(e))); + if(exitIfOk) { + if (ctx instanceof BaseMainActivity) { + BaseMainActivity.fullyExit(); + } else { + ((Activity) ctx).finish(); } - }) - .setCancelable(!exitIfOk); - try { - builder.show(); - } catch (Throwable th) { - th.printStackTrace(); - } + } + }) + .setCancelable(!exitIfOk); + try { + builder.show(); + } catch (Throwable th) { + th.printStackTrace(); } }; @@ -495,8 +490,8 @@ public final class Tools { } } - public static void dialogOnUiThread(final Activity ctx, final CharSequence title, final CharSequence message) { - ctx.runOnUiThread(() -> new AlertDialog.Builder(ctx) + public static void dialogOnUiThread(final Activity activity, final CharSequence title, final CharSequence message) { + activity.runOnUiThread(() -> new AlertDialog.Builder(activity) .setTitle(title) .setMessage(message) .setPositiveButton(android.R.string.ok, null) @@ -568,7 +563,7 @@ public final class Tools { }catch(IOException e) { throw new RuntimeException("Can't find the source version for "+ versionName +" (req version="+customVer.inheritsFrom+")"); } - inheritsVer.inheritsFrom = inheritsVer.id; + //inheritsVer.inheritsFrom = inheritsVer.id; insertSafety(inheritsVer, customVer, "assetIndex", "assets", "id", "mainClass", "minecraftArguments", @@ -664,23 +659,19 @@ public final class Tools { } public static String convertStream(InputStream inputStream, Charset charset) throws IOException { - String out = ""; + StringBuilder out = new StringBuilder(); int len; byte[] buf = new byte[512]; while((len = inputStream.read(buf))!=-1) { - out += new String(buf,0,len,charset); + out.append(new String(buf, 0, len, charset)); } - return out; + return out.toString(); } public static File lastFileModified(String dir) { File fl = new File(dir); - File[] files = fl.listFiles(new FileFilter() { - public boolean accept(File file) { - return file.isFile(); - } - }); + File[] files = fl.listFiles(File::isFile); long lastMod = Long.MIN_VALUE; File choice = null; @@ -696,13 +687,13 @@ public final class Tools { public static String read(InputStream is) throws IOException { - String out = ""; + StringBuilder out = new StringBuilder(); int len; byte[] buf = new byte[512]; while((len = is.read(buf))!=-1) { - out += new String(buf,0,len); + out.append(new String(buf, 0, len)); } - return out; + return out.toString(); } public static String read(String path) throws IOException { @@ -748,6 +739,7 @@ public final class Tools { public abstract static class DownloaderFeedback { public abstract void updateProgress(int curr, int max); } + public static void downloadFileMonitored(String urlInput,String nameOutput, DownloaderFeedback monitor) throws IOException { File nameOutputFile = new File(nameOutput); if (!nameOutputFile.exists()) { @@ -784,75 +776,6 @@ public final class Tools { return true; } } - public static class ZipTool - { - private ZipTool(){} - public static void zip(List files, File zipFile) throws IOException { - final int BUFFER_SIZE = 2048; - - BufferedInputStream origin = null; - ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile))); - - try { - byte data[] = new byte[BUFFER_SIZE]; - - for (File file : files) { - FileInputStream fileInputStream = new FileInputStream( file ); - - origin = new BufferedInputStream(fileInputStream, BUFFER_SIZE); - - try { - ZipEntry entry = new ZipEntry(file.getName()); - - out.putNextEntry(entry); - - int count; - while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) { - out.write(data, 0, count); - } - } - finally { - origin.close(); - } - } - } finally { - out.close(); - } - } - public static void unzip(File zipFile, File targetDirectory) throws IOException { - final int BUFFER_SIZE = 1024; - ZipInputStream zis = new ZipInputStream( - new BufferedInputStream(new FileInputStream(zipFile))); - try { - ZipEntry ze; - int count; - byte[] buffer = new byte[BUFFER_SIZE]; - while ((ze = zis.getNextEntry()) != null) { - File file = new File(targetDirectory, ze.getName()); - File dir = ze.isDirectory() ? file : file.getParentFile(); - if (!dir.isDirectory() && !dir.mkdirs()) - throw new FileNotFoundException("Failed to ensure directory: " + - dir.getAbsolutePath()); - if (ze.isDirectory()) - continue; - FileOutputStream fout = new FileOutputStream(file); - try { - while ((count = zis.read(buffer)) != -1) - fout.write(buffer, 0, count); - } finally { - fout.close(); - } - /* if time should be restored as well - long time = ze.getTime(); - if (time > 0) - file.setLastModified(time); - */ - } - } finally { - zis.close(); - } - } - } public static void ignoreNotch(boolean shouldIgnore, Activity ctx){ if (SDK_INT >= P) { diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Touchpad.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Touchpad.java index 348388bd7..80dec94dd 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Touchpad.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Touchpad.java @@ -27,19 +27,19 @@ import org.lwjgl.glfw.CallbackBridge; */ public class Touchpad extends FrameLayout { /* Whether the Touchpad should be displayed */ - private boolean displayState; + private boolean mDisplayState; /* Mouse pointer icon used by the touchpad */ - private final ImageView mousePointer = new ImageView(getContext()); + private final ImageView mMousePointerImageView = new ImageView(getContext()); /* Detect a classic android Tap */ - private final GestureDetector singleTapDetector = new GestureDetector(getContext(), new SingleTapConfirm()); + private final GestureDetector mSingleTapDetector = new GestureDetector(getContext(), new SingleTapConfirm()); /* Resolution scaler option, allow downsizing a window */ - private final float scaleFactor = DEFAULT_PREF.getInt("resolutionRatio",100)/100f; + private final float mScaleFactor = DEFAULT_PREF.getInt("resolutionRatio",100)/100f; /* Current pointer ID to move the mouse */ - private int currentPointerID = -1000; + private int mCurrentPointerID = -1000; /* Previous MotionEvent position, not scale */ - private float prevX, prevY; + private float mPrevX, mPrevY; /* Last first pointer positions non-scaled, used to scroll distance */ - private float scrollLastInitialX, scrollLastInitialY; + private float mScrollLastInitialX, mScrollLastInitialY; public Touchpad(@NonNull Context context) { this(context, null); @@ -50,56 +50,6 @@ public class Touchpad extends FrameLayout { init(); } - private void init(){ - // Setup mouse pointer - mousePointer.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.mouse_pointer, getContext().getTheme())); - mousePointer.post(() -> { - ViewGroup.LayoutParams params = mousePointer.getLayoutParams(); - params.width = (int) (36 / 100f * LauncherPreferences.PREF_MOUSESCALE); - params.height = (int) (54 / 100f * LauncherPreferences.PREF_MOUSESCALE); - }); - addView(mousePointer); - setFocusable(false); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - setDefaultFocusHighlightEnabled(false); - } - - // When the game is grabbing, we should not display the mouse - disable(); - displayState = false; - Thread virtualMouseGrabThread = new Thread(() -> { - while (true) { - if (!CallbackBridge.isGrabbing() && displayState && getVisibility() != VISIBLE) { - post(this::enable); - }else{ - if ((CallbackBridge.isGrabbing() && getVisibility() != View.GONE) || !displayState && getVisibility() == VISIBLE) { - post(this::disable); - } - } - - } - }, "VirtualMouseGrabThread"); - virtualMouseGrabThread.setPriority(Thread.MIN_PRIORITY); - virtualMouseGrabThread.start(); - } - - /** Enable the touchpad */ - public void enable(){ - setVisibility(VISIBLE); - placeMouseAt(currentDisplayMetrics.widthPixels / 2, currentDisplayMetrics.heightPixels / 2); - } - - /** Disable the touchpad and hides the mouse */ - public void disable(){ - setVisibility(GONE); - } - - /** @return The new state, enabled or disabled */ - public boolean switchState(){ - displayState = !displayState; - return displayState; - } - @Override public boolean onTouchEvent(MotionEvent event) { // MotionEvent reports input details from the touch screen @@ -114,77 +64,126 @@ public class Touchpad extends FrameLayout { float x = event.getX(); float y = event.getY(); - float mouseX = mousePointer.getX(); - float mouseY = mousePointer.getY(); + float mouseX = mMousePointerImageView.getX(); + float mouseY = mMousePointerImageView.getY(); - if (singleTapDetector.onTouchEvent(event)) { - CallbackBridge.mouseX = (mouseX * scaleFactor); - CallbackBridge.mouseY = (mouseY * scaleFactor); + if (mSingleTapDetector.onTouchEvent(event)) { + CallbackBridge.mouseX = (mouseX * mScaleFactor); + CallbackBridge.mouseY = (mouseY * mScaleFactor); CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); - CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT); + CallbackBridge.sendMouseKeycode(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT); return true; } switch (action) { case MotionEvent.ACTION_POINTER_DOWN: // 5 - scrollLastInitialX = event.getX(); - scrollLastInitialY = event.getY(); + mScrollLastInitialX = event.getX(); + mScrollLastInitialY = event.getY(); break; case MotionEvent.ACTION_DOWN: - prevX = x; - prevY = y; - currentPointerID = event.getPointerId(0); + mPrevX = x; + mPrevY = y; + mCurrentPointerID = event.getPointerId(0); break; case MotionEvent.ACTION_MOVE: // 2 //Scrolling feature if (!LauncherPreferences.PREF_DISABLE_GESTURES && !CallbackBridge.isGrabbing() && event.getPointerCount() >= 2) { - int hScroll = ((int) (event.getX() - scrollLastInitialX)) / FINGER_SCROLL_THRESHOLD; - int vScroll = ((int) (event.getY() - scrollLastInitialY)) / FINGER_SCROLL_THRESHOLD; + int hScroll = ((int) (event.getX() - mScrollLastInitialX)) / FINGER_SCROLL_THRESHOLD; + int vScroll = ((int) (event.getY() - mScrollLastInitialY)) / FINGER_SCROLL_THRESHOLD; if(vScroll != 0 || hScroll != 0){ CallbackBridge.sendScroll(hScroll, vScroll); - scrollLastInitialX = event.getX(); - scrollLastInitialY = event.getY(); + mScrollLastInitialX = event.getX(); + mScrollLastInitialY = event.getY(); } break; } // Mouse movement - if(currentPointerID == event.getPointerId(0)) { - mouseX = Math.max(0, Math.min(currentDisplayMetrics.widthPixels, mouseX + (x - prevX) * LauncherPreferences.PREF_MOUSESPEED)); - mouseY = Math.max(0, Math.min(currentDisplayMetrics.heightPixels, mouseY + (y - prevY) * LauncherPreferences.PREF_MOUSESPEED)); + if(mCurrentPointerID == event.getPointerId(0)) { + mouseX = Math.max(0, Math.min(currentDisplayMetrics.widthPixels, mouseX + (x - mPrevX) * LauncherPreferences.PREF_MOUSESPEED)); + mouseY = Math.max(0, Math.min(currentDisplayMetrics.heightPixels, mouseY + (y - mPrevY) * LauncherPreferences.PREF_MOUSESPEED)); placeMouseAt(mouseX, mouseY); CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); - }else currentPointerID = event.getPointerId(0); + }else mCurrentPointerID = event.getPointerId(0); - prevX = x; - prevY = y; + mPrevX = x; + mPrevY = y; break; case MotionEvent.ACTION_UP: - prevX = x; - prevY = y; - currentPointerID = -1000; + mPrevX = x; + mPrevY = y; + mCurrentPointerID = -1000; break; } - //debugText.setText(CallbackBridge.DEBUG_STRING.toString()); CallbackBridge.DEBUG_STRING.setLength(0); return true; } + /** Enable the touchpad */ + public void enable(){ + setVisibility(VISIBLE); + placeMouseAt(currentDisplayMetrics.widthPixels / 2, currentDisplayMetrics.heightPixels / 2); + } + + /** Disable the touchpad and hides the mouse */ + public void disable(){ + setVisibility(GONE); + } + + /** @return The new state, enabled or disabled */ + public boolean switchState(){ + mDisplayState = !mDisplayState; + return mDisplayState; + } + public void placeMouseAt(float x, float y) { - mousePointer.setX(x); - mousePointer.setY(y); - CallbackBridge.mouseX = (x * scaleFactor); - CallbackBridge.mouseY = (y * scaleFactor); + mMousePointerImageView.setX(x); + mMousePointerImageView.setY(y); + CallbackBridge.mouseX = (x * mScaleFactor); + CallbackBridge.mouseY = (y * mScaleFactor); CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); } + private void init(){ + // Setup mouse pointer + mMousePointerImageView.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_mouse_pointer, getContext().getTheme())); + mMousePointerImageView.post(() -> { + ViewGroup.LayoutParams params = mMousePointerImageView.getLayoutParams(); + params.width = (int) (36 / 100f * LauncherPreferences.PREF_MOUSESCALE); + params.height = (int) (54 / 100f * LauncherPreferences.PREF_MOUSESCALE); + }); + addView(mMousePointerImageView); + setFocusable(false); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + setDefaultFocusHighlightEnabled(false); + } + + // When the game is grabbing, we should not display the mouse + disable(); + mDisplayState = false; + Thread virtualMouseGrabThread = new Thread(() -> { + while (true) { + if (!CallbackBridge.isGrabbing() && mDisplayState && getVisibility() != VISIBLE) { + post(this::enable); + }else{ + if ((CallbackBridge.isGrabbing() && getVisibility() != View.GONE) || !mDisplayState && getVisibility() == VISIBLE) { + post(this::disable); + } + } + + } + }, "VirtualMouseGrabThread"); + virtualMouseGrabThread.setPriority(Thread.MIN_PRIORITY); + virtualMouseGrabThread.start(); + } + } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/microsoft/ui/MicrosoftLoginGUIActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/microsoft/ui/MicrosoftLoginGUIActivity.java index 6285cbb59..d82f17986 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/microsoft/ui/MicrosoftLoginGUIActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/microsoft/ui/MicrosoftLoginGUIActivity.java @@ -8,6 +8,7 @@ import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.ViewGroup; +import android.webkit.CookieManager; import android.webkit.WebResourceRequest; import android.webkit.WebSettings; import android.webkit.WebView; @@ -24,6 +25,7 @@ public class MicrosoftLoginGUIActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + CookieManager.getInstance().removeAllCookie(); waitDialog = new ProgressDialog(this); waitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); waitDialog.setIndeterminate(true); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/LoginListener.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/LoginListener.java deleted file mode 100644 index 444dffc6d..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/LoginListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.kdt.pojavlaunch.authenticator.mojang; - -public interface LoginListener -{ - public void onBeforeLogin(); - public void onLoginDone(String[] result); -} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/LoginTask.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/LoginTask.java deleted file mode 100644 index b61478e4e..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/LoginTask.java +++ /dev/null @@ -1,71 +0,0 @@ -package net.kdt.pojavlaunch.authenticator.mojang; - -import android.os.*; -import net.kdt.pojavlaunch.authenticator.mojang.yggdrasil.*; -import java.io.*; -import java.util.*; -import net.kdt.pojavlaunch.*; - -public class LoginTask extends AsyncTask -{ - private YggdrasilAuthenticator authenticator = new YggdrasilAuthenticator(); - //private String TAG = "MojangAuth-login"; - private LoginListener listener; - - public LoginTask setLoginListener(LoginListener listener) { - this.listener = listener; - return this; - } - - private UUID getRandomUUID() { - return UUID.randomUUID(); - } - - @Override - protected void onPreExecute() { - listener.onBeforeLogin(); - - super.onPreExecute(); - } - - @Override - protected Void doInBackground(String[] args) { - ArrayList str = new ArrayList(); - str.add("ERROR"); - try{ - try{ - AuthenticateResponse response = authenticator.authenticate(args[0], args[1], getRandomUUID()); - if (response.selectedProfile == null) { - str.add("Can't login a demo account!\n"); - } else { - if (new File(Tools.DIR_ACCOUNT_NEW + "/" + response.selectedProfile.name + ".json").exists()) { - str.add("This account already exist!\n"); - } else { - str.add(response.accessToken); // Access token - str.add(response.clientToken.toString()); // Client token - str.add(response.selectedProfile.id); // Profile ID - str.add(response.selectedProfile.name); // Username - str.set(0, "NORMAL"); - } - } - } - //MainActivity.updateStatus(804); - catch(Throwable e){ - str.add(e.getMessage()); - } - } - catch(Exception e){ - str.add(e.getMessage()); - } - - listener.onLoginDone(str.toArray(new String[0])); - - return null; - } - - @Override - protected void onPostExecute(Void result) { - // listener.onLoginDone(result); - super.onPostExecute(result); - } -} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/RefreshTokenTask.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/RefreshTokenTask.java deleted file mode 100644 index b7fb145e0..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/RefreshTokenTask.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.kdt.pojavlaunch.authenticator.mojang; - -import android.content.*; -import android.os.*; -import com.google.gson.*; - -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.util.*; -import net.kdt.pojavlaunch.*; -import net.kdt.pojavlaunch.authenticator.mojang.yggdrasil.*; -import android.app.*; -import net.kdt.pojavlaunch.value.*; - -public class RefreshTokenTask extends AsyncTask { - private YggdrasilAuthenticator authenticator = new YggdrasilAuthenticator(); - //private Gson gson = new Gson(); - private RefreshListener listener; - private MinecraftAccount profilePath; - - private final WeakReference ctx; - private ProgressDialog build; - - public RefreshTokenTask(Context ctx, RefreshListener listener) { - this.ctx = new WeakReference<>(ctx); - this.listener = listener; - } - - @Override - public void onPreExecute() { - build = new ProgressDialog(ctx.get()); - build.setMessage(ctx.get().getString(R.string.global_waiting)); - build.setProgressStyle(ProgressDialog.STYLE_SPINNER); - build.setCancelable(false); - build.show(); - } - - @Override - public Throwable doInBackground(String... args) { - try { - this.profilePath = MinecraftAccount.load(args[0]); - int responseCode = 400; - try { - responseCode = this.authenticator.validate(profilePath.accessToken).statusCode; - }catch(RuntimeException e) {} - - if (responseCode == 403) { - RefreshResponse response = this.authenticator.refresh(profilePath.accessToken, UUID.fromString(profilePath.clientToken)); - if (response == null) { - // Refresh when offline? - return null; - } else if (response.selectedProfile == null) { - throw new IllegalArgumentException("Can't refresh a demo account!"); - } - - profilePath.clientToken = response.clientToken.toString(); - profilePath.accessToken = response.accessToken; - profilePath.username = response.selectedProfile.name; - profilePath.profileId = response.selectedProfile.id; - } - profilePath.updateSkinFace(); - profilePath.save(); - return null; - } catch (Throwable e) { - return e; - } - } - - @Override - public void onPostExecute(Throwable result) { - build.dismiss(); - if (result == null) { - listener.onSuccess(profilePath); - } else { - listener.onFailed(result); - } - } -} - diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/AuthenticateRequest.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/AuthenticateRequest.java deleted file mode 100644 index f9dce5790..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/AuthenticateRequest.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil; - -import java.util.UUID; - -public class AuthenticateRequest { - public AgentInfo agent = new AgentInfo(); - public UUID clientToken; - public String password; - public String username; - - public static class AgentInfo { - public String name; - public int version; - } - - public AuthenticateRequest(String username, String password, UUID clientToken, String clientName, int clientVersion) { - this.username = username; - this.password = password; - this.clientToken = clientToken; - this.agent.name = clientName; - this.agent.version = clientVersion; - } -} - diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/AuthenticateResponse.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/AuthenticateResponse.java deleted file mode 100644 index 8989acd15..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/AuthenticateResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil; - -import java.util.UUID; - -public class AuthenticateResponse { - public String accessToken; - public Profile[] availableProfiles; - public UUID clientToken; - public Profile selectedProfile; -} - diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/RefreshResponse.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/RefreshResponse.java deleted file mode 100644 index b9a597955..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/RefreshResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.kdt.pojavlaunch.authenticator.mojang.yggdrasil; - -import java.util.UUID; - -public class RefreshResponse { - public String accessToken; - public UUID clientToken; - public Profile selectedProfile; -} - diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/YggdrasilAuthenticator.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/YggdrasilAuthenticator.java index fb3029608..8cf004610 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/YggdrasilAuthenticator.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/authenticator/mojang/yggdrasil/YggdrasilAuthenticator.java @@ -90,31 +90,6 @@ public class YggdrasilAuthenticator { } } - public AuthenticateResponse authenticate(String username, String password, UUID clientId) throws IOException, Throwable { - NetworkResponse obj = makeRequest("authenticate", new AuthenticateRequest(username, password, clientId, this.clientName, this.clientVersion), AuthenticateResponse.class); - /* - if (obj.statusCode != 200) { - throw new RuntimeException("Invalid username or password, status code: " + obj.statusCode); - } - */ - obj.throwExceptionIfNeed(); - return (AuthenticateResponse) obj.response; - } - - public RefreshResponse refresh(String authToken, UUID clientId) throws IOException, Throwable { - NetworkResponse obj = makeRequest("refresh", new RefreshRequest(authToken, clientId), RefreshResponse.class); - if (obj == null) { - return null; - } else { - obj.throwExceptionIfNeed(); // "Invalid username or password, status code: " + obj.statusCode); - return (RefreshResponse) obj.response; - } - } - - public NetworkResponse validate(String authToken) throws Throwable { - return makeRequest("validate", new RefreshRequest(authToken, null), null); - } - public NetworkResponse invalidate(String authToken, UUID clientId) throws Throwable { return makeRequest("invalidate", new RefreshRequest(authToken, clientId), null); } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlData.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlData.java index 11d210860..5a2ddded4 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlData.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlData.java @@ -14,13 +14,11 @@ import net.objecthunter.exp4j.function.Function; import org.lwjgl.glfw.*; -import static net.kdt.pojavlaunch.LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN; +import static net.kdt.pojavlaunch.LwjglGlfwKeycode.GLFW_KEY_UNKNOWN; import static org.lwjgl.glfw.CallbackBridge.sendKeyPress; import androidx.annotation.Keep; -import com.google.gson.annotations.SerializedName; - @Keep public class ControlData { diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlLayout.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlLayout.java index dfaf130d8..4975bb351 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlLayout.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlLayout.java @@ -16,8 +16,7 @@ import net.kdt.pojavlaunch.customcontrols.buttons.ControlSubButton; import net.kdt.pojavlaunch.customcontrols.handleview.HandleView; import net.kdt.pojavlaunch.prefs.*; -public class ControlLayout extends FrameLayout -{ +public class ControlLayout extends FrameLayout { protected CustomControls mLayout; private boolean mModifiable; private CustomControlsActivity mActivity; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/CustomControls.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/CustomControls.java index 6197cc17b..eade383fa 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/CustomControls.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/CustomControls.java @@ -3,12 +3,9 @@ import android.content.*; import androidx.annotation.Keep; -import com.google.gson.*; - import java.io.IOException; import java.util.*; import net.kdt.pojavlaunch.*; -import org.lwjgl.glfw.*; @Keep public class CustomControls { @@ -37,22 +34,22 @@ public class CustomControls { this.mControlDataList.add(new ControlData(ControlData.getSpecialButtons()[3])); // Secondary Mouse mControlDataList this.mControlDataList.add(new ControlData(ControlData.getSpecialButtons()[4])); // Virtual mouse toggle - this.mControlDataList.add(new ControlData(ctx, R.string.control_debug, new int[]{LWJGLGLFWKeycode.GLFW_KEY_F3}, "${margin}", "${margin}", false)); - this.mControlDataList.add(new ControlData(ctx, R.string.control_chat, new int[]{LWJGLGLFWKeycode.GLFW_KEY_T}, "${margin} * 2 + ${width}", "${margin}", false)); - this.mControlDataList.add(new ControlData(ctx, R.string.control_listplayers, new int[]{LWJGLGLFWKeycode.GLFW_KEY_TAB}, "${margin} * 4 + ${width} * 3", "${margin}", false)); - this.mControlDataList.add(new ControlData(ctx, R.string.control_thirdperson, new int[]{LWJGLGLFWKeycode.GLFW_KEY_F5}, "${margin}", "${height} + ${margin}", false)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_debug, new int[]{LwjglGlfwKeycode.GLFW_KEY_F3}, "${margin}", "${margin}", false)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_chat, new int[]{LwjglGlfwKeycode.GLFW_KEY_T}, "${margin} * 2 + ${width}", "${margin}", false)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_listplayers, new int[]{LwjglGlfwKeycode.GLFW_KEY_TAB}, "${margin} * 4 + ${width} * 3", "${margin}", false)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_thirdperson, new int[]{LwjglGlfwKeycode.GLFW_KEY_F5}, "${margin}", "${height} + ${margin}", false)); - this.mControlDataList.add(new ControlData(ctx, R.string.control_up, new int[]{LWJGLGLFWKeycode.GLFW_KEY_W}, "${margin} * 2 + ${width}", "${bottom} - ${margin} * 3 - ${height} * 2", true)); - this.mControlDataList.add(new ControlData(ctx, R.string.control_left, new int[]{LWJGLGLFWKeycode.GLFW_KEY_A}, "${margin}", "${bottom} - ${margin} * 2 - ${height}", true)); - this.mControlDataList.add(new ControlData(ctx, R.string.control_down, new int[]{LWJGLGLFWKeycode.GLFW_KEY_S}, "${margin} * 2 + ${width}", "${bottom} - ${margin}", true)); - this.mControlDataList.add(new ControlData(ctx, R.string.control_right, new int[]{LWJGLGLFWKeycode.GLFW_KEY_D}, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin} * 2 - ${height}", true)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_up, new int[]{LwjglGlfwKeycode.GLFW_KEY_W}, "${margin} * 2 + ${width}", "${bottom} - ${margin} * 3 - ${height} * 2", true)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_left, new int[]{LwjglGlfwKeycode.GLFW_KEY_A}, "${margin}", "${bottom} - ${margin} * 2 - ${height}", true)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_down, new int[]{LwjglGlfwKeycode.GLFW_KEY_S}, "${margin} * 2 + ${width}", "${bottom} - ${margin}", true)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_right, new int[]{LwjglGlfwKeycode.GLFW_KEY_D}, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin} * 2 - ${height}", true)); - this.mControlDataList.add(new ControlData(ctx, R.string.control_inventory, new int[]{LWJGLGLFWKeycode.GLFW_KEY_E}, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin}", true)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_inventory, new int[]{LwjglGlfwKeycode.GLFW_KEY_E}, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin}", true)); - ControlData shiftData = new ControlData(ctx, R.string.control_shift, new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT}, "${margin} * 2 + ${width}", "${screen_height} - ${margin} * 2 - ${height} * 2", true); + ControlData shiftData = new ControlData(ctx, R.string.control_shift, new int[]{LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT}, "${margin} * 2 + ${width}", "${screen_height} - ${margin} * 2 - ${height} * 2", true); shiftData.isToggle = true; this.mControlDataList.add(shiftData); - this.mControlDataList.add(new ControlData(ctx, R.string.control_jump, new int[]{LWJGLGLFWKeycode.GLFW_KEY_SPACE}, "${right} - ${margin} * 2 - ${width}", "${bottom} - ${margin} * 2 - ${height}", true)); + this.mControlDataList.add(new ControlData(ctx, R.string.control_jump, new int[]{LwjglGlfwKeycode.GLFW_KEY_SPACE}, "${right} - ${margin} * 2 - ${width}", "${bottom} - ${margin} * 2 - ${height}", true)); //The default controls are conform to the V2 version = 4; @@ -60,7 +57,7 @@ public class CustomControls { public void save(String path) throws IOException { - //Current version is the V2.4 so the version as to be marked as 4 ! + //Current version is the V2.5 so the version as to be marked as 4 ! version = 4; Tools.write(path, Tools.GLOBAL_GSON.toJson(this)); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/LayoutConverter.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/LayoutConverter.java index c0035ebac..c9316bca7 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/LayoutConverter.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/LayoutConverter.java @@ -2,7 +2,7 @@ package net.kdt.pojavlaunch.customcontrols; import com.google.gson.JsonSyntaxException; -import net.kdt.pojavlaunch.LWJGLGLFWKeycode; +import net.kdt.pojavlaunch.LwjglGlfwKeycode; import net.kdt.pojavlaunch.Tools; import org.json.JSONArray; @@ -83,10 +83,10 @@ public class LayoutConverter { for(int i = 0; i < layoutMainArray.length(); i++) { JSONObject button = layoutMainArray.getJSONObject(i); ControlData n_button = new ControlData(); - int[] keycodes = new int[] {LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, - LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, - LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, - LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN}; + int[] keycodes = new int[] {LwjglGlfwKeycode.GLFW_KEY_UNKNOWN, + LwjglGlfwKeycode.GLFW_KEY_UNKNOWN, + LwjglGlfwKeycode.GLFW_KEY_UNKNOWN, + LwjglGlfwKeycode.GLFW_KEY_UNKNOWN}; n_button.isDynamicBtn = button.getBoolean("isDynamicBtn"); n_button.dynamicX = button.getString("dynamicX"); n_button.dynamicY = button.getString("dynamicY"); @@ -116,9 +116,9 @@ public class LayoutConverter { } if(button.getBoolean("isRound")) { n_button.cornerRadius = 35f; } int next_idx = 0; - if(button.getBoolean("holdShift")) { keycodes[next_idx] = LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT; next_idx++; } - if(button.getBoolean("holdCtrl")) { keycodes[next_idx] = LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL; next_idx++; } - if(button.getBoolean("holdAlt")) { keycodes[next_idx] = LWJGLGLFWKeycode.GLFW_KEY_LEFT_ALT; next_idx++; } + if(button.getBoolean("holdShift")) { keycodes[next_idx] = LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT; next_idx++; } + if(button.getBoolean("holdCtrl")) { keycodes[next_idx] = LwjglGlfwKeycode.GLFW_KEY_LEFT_CONTROL; next_idx++; } + if(button.getBoolean("holdAlt")) { keycodes[next_idx] = LwjglGlfwKeycode.GLFW_KEY_LEFT_ALT; next_idx++; } keycodes[next_idx] = button.getInt("keycode"); n_button.keycodes = keycodes; empty.mControlDataList.add(n_button); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/TouchCharInput.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/TouchCharInput.java index 3d7c037df..890148363 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/TouchCharInput.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/TouchCharInput.java @@ -11,13 +11,11 @@ import android.content.res.Configuration; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.inputmethod.InputMethodManager; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import net.kdt.pojavlaunch.BaseMainActivity; -import net.kdt.pojavlaunch.LWJGLGLFWKeycode; +import net.kdt.pojavlaunch.LwjglGlfwKeycode; import net.kdt.pojavlaunch.R; import org.lwjgl.glfw.CallbackBridge; @@ -38,7 +36,7 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText } - private boolean isDoingInternalChanges = false; + private boolean mIsDoingInternalChanges = false; /** * We take the new chars, and send them to the game. @@ -48,10 +46,10 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); - if(isDoingInternalChanges)return; + if(mIsDoingInternalChanges)return; - for(int i=0; i< lengthBefore; ++i){ - CallbackBridge.sendKeycode(LWJGLGLFWKeycode.GLFW_KEY_BACKSPACE, '\u0008', 0, 0, true); + for(int i=0; i < lengthBefore; ++i){ + CallbackBridge.sendKeycode(LwjglGlfwKeycode.GLFW_KEY_BACKSPACE, '\u0008', 0, 0, true); } for(int i=start, count = 0; count < lengthAfter; ++i){ CallbackBridge.sendChar(text.charAt(i), 0); @@ -115,20 +113,12 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText */ @SuppressLint("SetTextI18n") public void clear(){ - isDoingInternalChanges = true; + mIsDoingInternalChanges = true; //Braille space, doesn't trigger keyboard auto-complete //replacing directly the text without though setText avoids notifying changes setText(" "); setSelection(getText().length()); - isDoingInternalChanges = false; - } - - /** - * Send the enter key. - */ - private void sendEnter(){ - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_ENTER); - clear(); + mIsDoingInternalChanges = false; } /** @@ -152,6 +142,13 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText setEnabled(false); } + /** + * Send the enter key. + */ + private void sendEnter(){ + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_ENTER); + clear(); + } /** * This function deals with anything that has to be executed when the constructor is called diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/buttons/ControlButton.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/buttons/ControlButton.java index a599ad80d..c11ab1484 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/buttons/ControlButton.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/buttons/ControlButton.java @@ -16,11 +16,10 @@ import net.kdt.pojavlaunch.customcontrols.ControlData; import net.kdt.pojavlaunch.customcontrols.ControlLayout; import net.kdt.pojavlaunch.customcontrols.handleview.*; import net.kdt.pojavlaunch.*; -import net.kdt.pojavlaunch.prefs.LauncherPreferences; import org.lwjgl.glfw.*; -import static net.kdt.pojavlaunch.LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN; +import static net.kdt.pojavlaunch.LwjglGlfwKeycode.GLFW_KEY_UNKNOWN; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_BUTTONSIZE; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_CONTROL_BOTTOM_OFFSET; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_CONTROL_LEFT_OFFSET; @@ -30,19 +29,15 @@ import static org.lwjgl.glfw.CallbackBridge.sendKeyPress; import static org.lwjgl.glfw.CallbackBridge.sendMouseButton; @SuppressLint("ViewConstructor") -public class ControlButton extends androidx.appcompat.widget.AppCompatButton implements OnLongClickListener -{ - private final Paint mRectPaint = new Paint();; - +public class ControlButton extends androidx.appcompat.widget.AppCompatButton implements OnLongClickListener { + private final Paint mRectPaint = new Paint(); protected GestureDetector mGestureDetector; protected ControlData mProperties; protected SelectionEndHandleView mHandleView; - protected boolean mModifiable = false; protected boolean mCanTriggerLongClick = true; - - protected boolean isToggled = false; - protected boolean isPointerOutOfBounds = false; + protected boolean mIsToggled = false; + protected boolean mIsPointerOutOfBounds = false; public ControlButton(ControlLayout layout, ControlData properties) { super(layout.getContext()); @@ -259,7 +254,7 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - if (isToggled || (!mProperties.isToggle && isActivated())) + if (mIsToggled || (!mProperties.isToggle && isActivated())) canvas.drawRoundRect(0, 0, getWidth(), getHeight(), mProperties.cornerRadius, mProperties.cornerRadius, mRectPaint); } @@ -304,26 +299,26 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp //If out of bounds if(event.getX() < getLeft() || event.getX() > getRight() || event.getY() < getTop() || event.getY() > getBottom()){ - if(mProperties.isSwipeable && !isPointerOutOfBounds){ + if(mProperties.isSwipeable && !mIsPointerOutOfBounds){ //Remove keys if(!triggerToggle()) { sendKeyPresses(false); } } - isPointerOutOfBounds = true; + mIsPointerOutOfBounds = true; ((ControlLayout) getParent()).onTouch(this, event); break; } //Else if we now are in bounds - if(isPointerOutOfBounds) { + if(mIsPointerOutOfBounds) { ((ControlLayout) getParent()).onTouch(this, event); //RE-press the button if(mProperties.isSwipeable && !mProperties.isToggle){ sendKeyPresses(true); } } - isPointerOutOfBounds = false; + mIsPointerOutOfBounds = false; break; case MotionEvent.ACTION_DOWN: // 0 @@ -340,8 +335,8 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp MinecraftGLView v = ((ControlLayout) this.getParent()).findViewById(R.id.main_game_render_view); if (v != null) v.dispatchTouchEvent(event); } - if(isPointerOutOfBounds) ((ControlLayout) getParent()).onTouch(this, event); - isPointerOutOfBounds = false; + if(mIsPointerOutOfBounds) ((ControlLayout) getParent()).onTouch(this, event); + mIsPointerOutOfBounds = false; if(!triggerToggle()) { sendKeyPresses(false); @@ -501,9 +496,9 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp public boolean triggerToggle(){ //returns true a the toggle system is triggered if(mProperties.isToggle){ - isToggled = !isToggled; + mIsToggled = !mIsToggled; invalidate(); - sendKeyPresses(isToggled); + sendKeyPresses(mIsToggled); return true; } return false; @@ -536,15 +531,15 @@ public class ControlButton extends androidx.appcompat.widget.AppCompatButton imp break; case ControlData.SPECIALBTN_MOUSEPRI: - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown); + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown); break; case ControlData.SPECIALBTN_MOUSEMID: - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_MIDDLE, isDown); + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_MIDDLE, isDown); break; case ControlData.SPECIALBTN_MOUSESEC: - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown); + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown); break; case ControlData.SPECIALBTN_SCROLLDOWN: diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/buttons/ControlDrawer.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/buttons/ControlDrawer.java index a7fbb154c..d048ab99f 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/buttons/ControlDrawer.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/buttons/ControlDrawer.java @@ -2,7 +2,6 @@ package net.kdt.pojavlaunch.customcontrols.buttons; import android.annotation.SuppressLint; import android.view.MotionEvent; -import android.view.View; import android.view.ViewGroup; import net.kdt.pojavlaunch.Tools; @@ -20,7 +19,7 @@ public class ControlDrawer extends ControlButton { public ArrayList buttons; public ControlDrawerData drawerData; - public ControlLayout mLayout; + public ControlLayout layout; public boolean areButtonsVisible; @@ -28,14 +27,14 @@ public class ControlDrawer extends ControlButton { super(layout, drawerData.properties); buttons = new ArrayList<>(drawerData.buttonProperties.size()); - mLayout = layout; + this.layout = layout; this.drawerData = drawerData; areButtonsVisible = layout.getModifiable(); } public void addButton(ControlData properties){ - addButton(new ControlSubButton(mLayout, properties, this)); + addButton(new ControlSubButton(layout, properties, this)); } public void addButton(ControlSubButton button){ diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java index 81db7f57f..c13ed6e76 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java @@ -15,7 +15,7 @@ import android.widget.Toast; import androidx.core.content.res.ResourcesCompat; import androidx.core.math.MathUtils; -import net.kdt.pojavlaunch.LWJGLGLFWKeycode; +import net.kdt.pojavlaunch.LwjglGlfwKeycode; import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.prefs.LauncherPreferences; import net.kdt.pojavlaunch.utils.MCOptionUtils; @@ -40,60 +40,60 @@ import static org.lwjgl.glfw.CallbackBridge.sendMouseButton; public class Gamepad { /* Resolution scaler option, allow downsizing a window */ - private final float scaleFactor = LauncherPreferences.DEFAULT_PREF.getInt("resolutionRatio",100)/100f; + private final float mScaleFactor = LauncherPreferences.DEFAULT_PREF.getInt("resolutionRatio",100)/100f; /* Mouse positions, scaled by the scaleFactor */ - private float mouse_x, mouse_y; + private float mMouse_x, mMouse_y; /* Sensitivity, adjusted according to screen size */ - private final double sensitivityFactor = (1.4 * (1080f/ currentDisplayMetrics.heightPixels)); + private final double mSensitivityFactor = (1.4 * (1080f/ currentDisplayMetrics.heightPixels)); - private final ImageView pointerView; + private final ImageView mPointerImageView; - private final GamepadDpad gamepadDpad = new GamepadDpad(); + private final GamepadDpad mGamepadDpad = new GamepadDpad(); - private final GamepadJoystick leftJoystick; - private int currentJoystickDirection = DIRECTION_NONE; + private final GamepadJoystick mLeftJoystick; + private int mCurrentJoystickDirection = DIRECTION_NONE; - private final GamepadJoystick rightJoystick; - private float lastHorizontalValue = 0.0f; - private float lastVerticalValue = 0.0f; + private final GamepadJoystick mRightJoystick; + private float mLastHorizontalValue = 0.0f; + private float mLastVerticalValue = 0.0f; - private final double mouseMaxAcceleration = 2f; + private final double MOUSE_MAX_ACCELERATION = 2f; - private double mouseMagnitude; - private double mouseAngle; - private double mouseSensitivity = 19; + private double mMouseMagnitude; + private double mMouseAngle; + private double mMouseSensitivity = 19; - private final GamepadMap gameMap = GamepadMap.getDefaultGameMap(); - private final GamepadMap menuMap = GamepadMap.getDefaultMenuMap(); - private GamepadMap currentMap = gameMap; + private final GamepadMap mGameMap = GamepadMap.getDefaultGameMap(); + private final GamepadMap mMenuMap = GamepadMap.getDefaultMenuMap(); + private GamepadMap mCurrentMap = mGameMap; - private boolean lastGrabbingState = true; + private boolean mLastGrabbingState = true; //private final boolean mModifierDigitalTriggers; private final boolean mModifierAnalogTriggers; private boolean mModifierSwappedAxis = true; //Triggers and right stick axis are swapped. /* Choreographer with time to compute delta on ticking */ - private final Choreographer screenChoreographer; - private long lastFrameTime; + private final Choreographer mScreenChoreographer; + private long mLastFrameTime; /* Listen for change in gui scale */ - private MCOptionUtils.MCOptionListener GUIScaleListener = () -> notifyGUISizeChange(getMcScale()); + private MCOptionUtils.MCOptionListener mGuiScaleListener = () -> notifyGUISizeChange(getMcScale()); public Gamepad(View contextView, InputDevice inputDevice){ - screenChoreographer = Choreographer.getInstance(); + mScreenChoreographer = Choreographer.getInstance(); Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { updateGrabbingState(); tick(frameTimeNanos); - screenChoreographer.postFrameCallback(this); + mScreenChoreographer.postFrameCallback(this); } }; - screenChoreographer.postFrameCallback(frameCallback); - lastFrameTime = System.nanoTime(); + mScreenChoreographer.postFrameCallback(frameCallback); + mLastFrameTime = System.nanoTime(); /* Add the listener for the cross hair */ - MCOptionUtils.addMCOptionListener(GUIScaleListener); + MCOptionUtils.addMCOptionListener(mGuiScaleListener); Toast.makeText(contextView.getContext(),"GAMEPAD CREATED", Toast.LENGTH_LONG).show(); for(InputDevice.MotionRange range : inputDevice.getMotionRanges()){ @@ -106,98 +106,31 @@ public class Gamepad { } } - leftJoystick = new GamepadJoystick(MotionEvent.AXIS_X, MotionEvent.AXIS_Y, inputDevice); + mLeftJoystick = new GamepadJoystick(MotionEvent.AXIS_X, MotionEvent.AXIS_Y, inputDevice); if(!mModifierSwappedAxis) - rightJoystick = new GamepadJoystick(MotionEvent.AXIS_Z, MotionEvent.AXIS_RZ, inputDevice); + mRightJoystick = new GamepadJoystick(MotionEvent.AXIS_Z, MotionEvent.AXIS_RZ, inputDevice); else - rightJoystick = new GamepadJoystick(MotionEvent.AXIS_RX, MotionEvent.AXIS_RY, inputDevice); + mRightJoystick = new GamepadJoystick(MotionEvent.AXIS_RX, MotionEvent.AXIS_RY, inputDevice); //mModifierDigitalTriggers = inputDevice.hasKeys(KeyEvent.KEYCODE_BUTTON_R2)[0]; mModifierAnalogTriggers = supportAnalogTriggers(inputDevice); Context ctx = contextView.getContext(); - pointerView = new ImageView(contextView.getContext()); - pointerView.setImageDrawable(ResourcesCompat.getDrawable(ctx.getResources(), R.drawable.pointer, ctx.getTheme())); - pointerView.getDrawable().setFilterBitmap(false); + mPointerImageView = new ImageView(contextView.getContext()); + mPointerImageView.setImageDrawable(ResourcesCompat.getDrawable(ctx.getResources(), R.drawable.ic_gamepad_pointer, ctx.getTheme())); + mPointerImageView.getDrawable().setFilterBitmap(false); - int size = (int) ((22 * getMcScale()) / scaleFactor); - pointerView.setLayoutParams(new FrameLayout.LayoutParams(size, size)); + int size = (int) ((22 * getMcScale()) / mScaleFactor); + mPointerImageView.setLayoutParams(new FrameLayout.LayoutParams(size, size)); - mouse_x = CallbackBridge.windowWidth/2; - mouse_y = CallbackBridge.windowHeight/2; - CallbackBridge.sendCursorPos(mouse_x, mouse_y); + mMouse_x = CallbackBridge.windowWidth/2; + mMouse_y = CallbackBridge.windowHeight/2; + CallbackBridge.sendCursorPos(mMouse_x, mMouse_y); placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2); - ((ViewGroup)contextView.getParent()).addView(pointerView); + ((ViewGroup)contextView.getParent()).addView(mPointerImageView); } - /** - * Send the new mouse position, computing the delta - * @param frameTimeNanos The time to render the frame, used to compute mouse delta - */ - public void tick(long frameTimeNanos){ - //update mouse position - if(lastHorizontalValue != 0 || lastVerticalValue != 0){ - GamepadJoystick currentJoystick = lastGrabbingState ? leftJoystick : rightJoystick; - - double acceleration = (mouseMagnitude - currentJoystick.getDeadzone()) / (1 - currentJoystick.getDeadzone()); - acceleration = Math.pow(acceleration, mouseMaxAcceleration); - if(acceleration > 1) acceleration = 1; - - // Compute delta since last tick time - float deltaX = (float) (Math.cos(mouseAngle) * acceleration * mouseSensitivity); - float deltaY = (float) (Math.sin(mouseAngle) * acceleration * mouseSensitivity); - float deltaTimeScale = ((frameTimeNanos - lastFrameTime) / 16666666f); // Scale of 1 = 60Hz - deltaX *= deltaTimeScale; - deltaY *= deltaTimeScale; - - CallbackBridge.mouseX += deltaX; - CallbackBridge.mouseY -= deltaY; - - if(!lastGrabbingState){ - CallbackBridge.mouseX = MathUtils.clamp(CallbackBridge.mouseX, 0, CallbackBridge.windowWidth); - CallbackBridge.mouseY = MathUtils.clamp(CallbackBridge.mouseY, 0, CallbackBridge.windowHeight); - placePointerView((int) (CallbackBridge.mouseX / scaleFactor), (int) (CallbackBridge.mouseY/ scaleFactor)); - } - - mouse_x = CallbackBridge.mouseX; - mouse_y = CallbackBridge.mouseY; - - //Send the mouse to the game - CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); - } - - // Update last nano time - lastFrameTime = frameTimeNanos; - } - - /** Update the grabbing state, and change the currentMap, mouse position and sensibility */ - private void updateGrabbingState() { - boolean lastGrabbingValue = lastGrabbingState; - lastGrabbingState = CallbackBridge.isGrabbing(); - if(lastGrabbingValue == lastGrabbingState) return; - - // Switch grabbing state then - currentMap.resetPressedState(); - if(lastGrabbingState){ - currentMap = gameMap; - pointerView.setVisibility(View.INVISIBLE); - mouseSensitivity = 18; - return; - } - - currentMap = menuMap; - sendDirectionalKeycode(currentJoystickDirection, false, gameMap); // removing what we were doing - - mouse_x = CallbackBridge.windowWidth/2; - mouse_y = CallbackBridge.windowHeight/2; - CallbackBridge.sendCursorPos(mouse_x, mouse_y); - placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2); - pointerView.setVisibility(View.VISIBLE); - // Sensitivity in menu is MC and HARDWARE resolution dependent - mouseSensitivity = 19 * scaleFactor / sensitivityFactor; - - } public void update(KeyEvent event){ sendButton(event); @@ -208,125 +141,17 @@ public class Gamepad { updateMouseJoystick(event); updateAnalogTriggers(event); - int[] dpadEvent = gamepadDpad.convertEvent(event); + int[] dpadEvent = mGamepadDpad.convertEvent(event); sendButton(dpadEvent[0], dpadEvent[1]); } - private void updateMouseJoystick(MotionEvent event){ - GamepadJoystick currentJoystick = lastGrabbingState ? rightJoystick : leftJoystick; - float horizontalValue = currentJoystick.getHorizontalAxis(event); - float verticalValue = currentJoystick.getVerticalAxis(event); - if(horizontalValue != lastHorizontalValue || verticalValue != lastVerticalValue){ - lastHorizontalValue = horizontalValue; - lastVerticalValue = verticalValue; - - mouseMagnitude = currentJoystick.getMagnitude(event); - mouseAngle = currentJoystick.getAngleRadian(event); - - tick(System.nanoTime()); - return; - } - lastHorizontalValue = horizontalValue; - lastVerticalValue = verticalValue; - - mouseMagnitude = currentJoystick.getMagnitude(event); - mouseAngle = currentJoystick.getAngleRadian(event); - - } - - private void updateDirectionalJoystick(MotionEvent event){ - GamepadJoystick currentJoystick = lastGrabbingState ? leftJoystick : rightJoystick; - - int lastJoystickDirection = currentJoystickDirection; - currentJoystickDirection = currentJoystick.getHeightDirection(event); - - if(currentJoystickDirection == lastJoystickDirection) return; - - sendDirectionalKeycode(lastJoystickDirection, false, getCurrentMap()); - sendDirectionalKeycode(currentJoystickDirection, true, getCurrentMap()); - } - - private void updateAnalogTriggers(MotionEvent event){ - if(mModifierAnalogTriggers){ - getCurrentMap().TRIGGER_LEFT.update( - (event.getAxisValue(MotionEvent.AXIS_LTRIGGER) > 0.5) - || (event.getAxisValue(MotionEvent.AXIS_BRAKE) > 0.5) - || (mModifierSwappedAxis &&(event.getAxisValue(MotionEvent.AXIS_Z) > 0.5)) ); - getCurrentMap().TRIGGER_RIGHT.update( - (event.getAxisValue( MotionEvent.AXIS_RTRIGGER) > 0.5) - || (event.getAxisValue(MotionEvent.AXIS_GAS) > 0.5) - || (mModifierSwappedAxis && event.getAxisValue(MotionEvent.AXIS_RZ) > 0.5) ); - } - } - public void notifyGUISizeChange(int newSize){ //Change the pointer size to match UI - int size = (int) ((22 * newSize) / scaleFactor); - pointerView.post(() -> pointerView.setLayoutParams(new FrameLayout.LayoutParams(size, size))); + int size = (int) ((22 * newSize) / mScaleFactor); + mPointerImageView.post(() -> mPointerImageView.setLayoutParams(new FrameLayout.LayoutParams(size, size))); } - /** - * Detect if a gamepad supports analog triggers - * @param inputDevice The input device with all the MotionRange - * @return Whether the gamepad supports analog triggers - */ - private boolean supportAnalogTriggers(InputDevice inputDevice){ - for(InputDevice.MotionRange motionRange : inputDevice.getMotionRanges()){ - int axis = motionRange.getAxis(); - - if( axis == MotionEvent.AXIS_BRAKE || axis == MotionEvent.AXIS_GAS || - axis == MotionEvent.AXIS_LTRIGGER || axis == MotionEvent.AXIS_RTRIGGER || - (mModifierSwappedAxis && axis == MotionEvent.AXIS_Z) || - (mModifierSwappedAxis && axis == MotionEvent.AXIS_RZ)){ - return true; - } - } - return false; - } - - private GamepadMap getCurrentMap(){ - return currentMap; - } - - private static void sendDirectionalKeycode(int direction, boolean isDown, GamepadMap map){ - switch (direction){ - case DIRECTION_NORTH: - sendInput(map.DIRECTION_FORWARD, isDown); - break; - case DIRECTION_NORTH_EAST: - sendInput(map.DIRECTION_FORWARD, isDown); - sendInput(map.DIRECTION_RIGHT, isDown); - break; - case DIRECTION_EAST: - sendInput(map.DIRECTION_RIGHT, isDown); - break; - case DIRECTION_SOUTH_EAST: - sendInput(map.DIRECTION_RIGHT, isDown); - sendInput(map.DIRECTION_BACKWARD, isDown); - break; - case DIRECTION_SOUTH: - sendInput(map.DIRECTION_BACKWARD, isDown); - break; - case DIRECTION_SOUTH_WEST: - sendInput(map.DIRECTION_BACKWARD, isDown); - sendInput(map.DIRECTION_LEFT, isDown); - break; - case DIRECTION_WEST: - sendInput(map.DIRECTION_LEFT, isDown); - break; - case DIRECTION_NORTH_WEST: - sendInput(map.DIRECTION_FORWARD, isDown); - sendInput(map.DIRECTION_LEFT, isDown); - break; - } - } - - private void placePointerView(int x, int y){ - pointerView.setX(x - pointerView.getWidth()/2); - pointerView.setY(y - pointerView.getHeight()/2); - } - public void sendButton(KeyEvent event){ sendButton(event.getKeyCode(), event.getAction()); } @@ -403,7 +228,7 @@ public class Gamepad { default: - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_SPACE, CallbackBridge.getCurrentMods(), isDown); + sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_SPACE, CallbackBridge.getCurrentMods(), isDown); break; } } @@ -418,11 +243,11 @@ public class Gamepad { if(isDown) CallbackBridge.sendScroll(0, 1); break; - case LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT: - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown); + case LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT: + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown); break; - case LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT: - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown); + case LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT: + sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown); break; @@ -443,4 +268,180 @@ public class Gamepad { return ((event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD || GamepadDpad.isDpadEvent(event) ); } + + /** + * Send the new mouse position, computing the delta + * @param frameTimeNanos The time to render the frame, used to compute mouse delta + */ + private void tick(long frameTimeNanos){ + //update mouse position + if(mLastHorizontalValue != 0 || mLastVerticalValue != 0){ + GamepadJoystick currentJoystick = mLastGrabbingState ? mLeftJoystick : mRightJoystick; + + double acceleration = (mMouseMagnitude - currentJoystick.getDeadzone()) / (1 - currentJoystick.getDeadzone()); + acceleration = Math.pow(acceleration, MOUSE_MAX_ACCELERATION); + if(acceleration > 1) acceleration = 1; + + // Compute delta since last tick time + float deltaX = (float) (Math.cos(mMouseAngle) * acceleration * mMouseSensitivity); + float deltaY = (float) (Math.sin(mMouseAngle) * acceleration * mMouseSensitivity); + float deltaTimeScale = ((frameTimeNanos - mLastFrameTime) / 16666666f); // Scale of 1 = 60Hz + deltaX *= deltaTimeScale; + deltaY *= deltaTimeScale; + + CallbackBridge.mouseX += deltaX; + CallbackBridge.mouseY -= deltaY; + + if(!mLastGrabbingState){ + CallbackBridge.mouseX = MathUtils.clamp(CallbackBridge.mouseX, 0, CallbackBridge.windowWidth); + CallbackBridge.mouseY = MathUtils.clamp(CallbackBridge.mouseY, 0, CallbackBridge.windowHeight); + placePointerView((int) (CallbackBridge.mouseX / mScaleFactor), (int) (CallbackBridge.mouseY/ mScaleFactor)); + } + + mMouse_x = CallbackBridge.mouseX; + mMouse_y = CallbackBridge.mouseY; + + //Send the mouse to the game + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); + } + + // Update last nano time + mLastFrameTime = frameTimeNanos; + } + + /** Update the grabbing state, and change the currentMap, mouse position and sensibility */ + private void updateGrabbingState() { + boolean lastGrabbingValue = mLastGrabbingState; + mLastGrabbingState = CallbackBridge.isGrabbing(); + if(lastGrabbingValue == mLastGrabbingState) return; + + // Switch grabbing state then + mCurrentMap.resetPressedState(); + if(mLastGrabbingState){ + mCurrentMap = mGameMap; + mPointerImageView.setVisibility(View.INVISIBLE); + mMouseSensitivity = 18; + return; + } + + mCurrentMap = mMenuMap; + sendDirectionalKeycode(mCurrentJoystickDirection, false, mGameMap); // removing what we were doing + + mMouse_x = CallbackBridge.windowWidth/2; + mMouse_y = CallbackBridge.windowHeight/2; + CallbackBridge.sendCursorPos(mMouse_x, mMouse_y); + placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2); + mPointerImageView.setVisibility(View.VISIBLE); + // Sensitivity in menu is MC and HARDWARE resolution dependent + mMouseSensitivity = 19 * mScaleFactor / mSensitivityFactor; + + } + + private void updateMouseJoystick(MotionEvent event){ + GamepadJoystick currentJoystick = mLastGrabbingState ? mRightJoystick : mLeftJoystick; + float horizontalValue = currentJoystick.getHorizontalAxis(event); + float verticalValue = currentJoystick.getVerticalAxis(event); + if(horizontalValue != mLastHorizontalValue || verticalValue != mLastVerticalValue){ + mLastHorizontalValue = horizontalValue; + mLastVerticalValue = verticalValue; + + mMouseMagnitude = currentJoystick.getMagnitude(event); + mMouseAngle = currentJoystick.getAngleRadian(event); + + tick(System.nanoTime()); + return; + } + mLastHorizontalValue = horizontalValue; + mLastVerticalValue = verticalValue; + + mMouseMagnitude = currentJoystick.getMagnitude(event); + mMouseAngle = currentJoystick.getAngleRadian(event); + + } + + private void updateDirectionalJoystick(MotionEvent event){ + GamepadJoystick currentJoystick = mLastGrabbingState ? mLeftJoystick : mRightJoystick; + + int lastJoystickDirection = mCurrentJoystickDirection; + mCurrentJoystickDirection = currentJoystick.getHeightDirection(event); + + if(mCurrentJoystickDirection == lastJoystickDirection) return; + + sendDirectionalKeycode(lastJoystickDirection, false, getCurrentMap()); + sendDirectionalKeycode(mCurrentJoystickDirection, true, getCurrentMap()); + } + + private void updateAnalogTriggers(MotionEvent event){ + if(mModifierAnalogTriggers){ + getCurrentMap().TRIGGER_LEFT.update( + (event.getAxisValue(MotionEvent.AXIS_LTRIGGER) > 0.5) + || (event.getAxisValue(MotionEvent.AXIS_BRAKE) > 0.5) + || (mModifierSwappedAxis &&(event.getAxisValue(MotionEvent.AXIS_Z) > 0.5)) ); + getCurrentMap().TRIGGER_RIGHT.update( + (event.getAxisValue( MotionEvent.AXIS_RTRIGGER) > 0.5) + || (event.getAxisValue(MotionEvent.AXIS_GAS) > 0.5) + || (mModifierSwappedAxis && event.getAxisValue(MotionEvent.AXIS_RZ) > 0.5) ); + } + } + + /** + * Detect if a gamepad supports analog triggers + * @param inputDevice The input device with all the MotionRange + * @return Whether the gamepad supports analog triggers + */ + private boolean supportAnalogTriggers(InputDevice inputDevice){ + for(InputDevice.MotionRange motionRange : inputDevice.getMotionRanges()){ + int axis = motionRange.getAxis(); + + if( axis == MotionEvent.AXIS_BRAKE || axis == MotionEvent.AXIS_GAS || + axis == MotionEvent.AXIS_LTRIGGER || axis == MotionEvent.AXIS_RTRIGGER || + (mModifierSwappedAxis && axis == MotionEvent.AXIS_Z) || + (mModifierSwappedAxis && axis == MotionEvent.AXIS_RZ)){ + return true; + } + } + return false; + } + + private GamepadMap getCurrentMap(){ + return mCurrentMap; + } + + private static void sendDirectionalKeycode(int direction, boolean isDown, GamepadMap map){ + switch (direction){ + case DIRECTION_NORTH: + sendInput(map.DIRECTION_FORWARD, isDown); + break; + case DIRECTION_NORTH_EAST: + sendInput(map.DIRECTION_FORWARD, isDown); + sendInput(map.DIRECTION_RIGHT, isDown); + break; + case DIRECTION_EAST: + sendInput(map.DIRECTION_RIGHT, isDown); + break; + case DIRECTION_SOUTH_EAST: + sendInput(map.DIRECTION_RIGHT, isDown); + sendInput(map.DIRECTION_BACKWARD, isDown); + break; + case DIRECTION_SOUTH: + sendInput(map.DIRECTION_BACKWARD, isDown); + break; + case DIRECTION_SOUTH_WEST: + sendInput(map.DIRECTION_BACKWARD, isDown); + sendInput(map.DIRECTION_LEFT, isDown); + break; + case DIRECTION_WEST: + sendInput(map.DIRECTION_LEFT, isDown); + break; + case DIRECTION_NORTH_WEST: + sendInput(map.DIRECTION_FORWARD, isDown); + sendInput(map.DIRECTION_LEFT, isDown); + break; + } + } + + private void placePointerView(int x, int y){ + mPointerImageView.setX(x - mPointerImageView.getWidth()/2); + mPointerImageView.setY(y - mPointerImageView.getHeight()/2); + } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadButton.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadButton.java index f502ff60f..a6c7cc1e7 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadButton.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadButton.java @@ -2,15 +2,15 @@ package net.kdt.pojavlaunch.customcontrols.gamepad; import android.view.KeyEvent; +/** + * Simple button able to store its state and some properties + */ public class GamepadButton { - /* - Just a simple button, that auto deal with the great habit from android to just SPAAAMS input events - */ public int[] keycodes; public boolean isToggleable = false; - private boolean isDown = false; - private boolean isToggled = false; + private boolean mIsDown = false; + private boolean mIsToggled = false; public void update(KeyEvent event){ boolean isKeyDown = (event.getAction() == KeyEvent.ACTION_DOWN); @@ -18,29 +18,29 @@ public class GamepadButton { } public void update(boolean isKeyDown){ - if(isKeyDown != isDown){ - isDown = isKeyDown; + if(isKeyDown != mIsDown){ + mIsDown = isKeyDown; if(isToggleable){ if(isKeyDown){ - isToggled = !isToggled; - Gamepad.sendInput(keycodes, isToggled); + mIsToggled = !mIsToggled; + Gamepad.sendInput(keycodes, mIsToggled); } return; } - Gamepad.sendInput(keycodes, isDown); + Gamepad.sendInput(keycodes, mIsDown); } } public void resetButtonState(){ - if(isDown || isToggled){ + if(mIsDown || mIsToggled){ Gamepad.sendInput(keycodes, false); } - isDown = false; - isToggled = false; + mIsDown = false; + mIsToggled = false; } public boolean isDown(){ - return isToggleable ? isToggled : isDown; + return isToggleable ? mIsToggled : mIsDown; } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadDpad.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadDpad.java index bf365b731..cba9484bd 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadDpad.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadDpad.java @@ -5,7 +5,6 @@ import android.view.KeyEvent; import android.view.MotionEvent; import static android.view.InputDevice.KEYBOARD_TYPE_NON_ALPHABETIC; -import static android.view.InputDevice.SOURCE_DPAD; import static android.view.KeyEvent.KEYCODE_DPAD_CENTER; import static android.view.KeyEvent.KEYCODE_DPAD_DOWN; import static android.view.KeyEvent.KEYCODE_DPAD_LEFT; @@ -14,7 +13,7 @@ import static android.view.KeyEvent.KEYCODE_DPAD_UP; public class GamepadDpad { - private int lastKeycode = KEYCODE_DPAD_CENTER; + private int mLastKeycode = KEYCODE_DPAD_CENTER; /** * Convert the event to a 2 int array: keycode and keyAction, similar to a keyEvent @@ -30,22 +29,22 @@ public class GamepadDpad { // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad // LEFT and RIGHT direction accordingly. if (Float.compare(xaxis, -1.0f) == 0) { - lastKeycode = KEYCODE_DPAD_LEFT; + mLastKeycode = KEYCODE_DPAD_LEFT; } else if (Float.compare(xaxis, 1.0f) == 0) { - lastKeycode = KEYCODE_DPAD_RIGHT; + mLastKeycode = KEYCODE_DPAD_RIGHT; } // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad // UP and DOWN direction accordingly. else if (Float.compare(yaxis, -1.0f) == 0) { - lastKeycode = KEYCODE_DPAD_UP; + mLastKeycode = KEYCODE_DPAD_UP; } else if (Float.compare(yaxis, 1.0f) == 0) { - lastKeycode = KEYCODE_DPAD_DOWN; + mLastKeycode = KEYCODE_DPAD_DOWN; }else { //No keycode change action = KeyEvent.ACTION_UP; } - return new int[]{lastKeycode, action}; + return new int[]{mLastKeycode, action}; } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadJoystick.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadJoystick.java index 22cb0b999..7f0487b49 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadJoystick.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadJoystick.java @@ -20,17 +20,14 @@ public class GamepadJoystick { public static final int DIRECTION_SOUTH = 6; public static final int DIRECTION_SOUTH_EAST = 7; - private final InputDevice device; - - private final int verticalAxis; - private final int horizontalAxis; + private final InputDevice mInputDevice; + private final int mVerticalAxis; + private final int mHorizontalAxis; public GamepadJoystick(int horizontalAxis, int verticalAxis, InputDevice device){ - this.verticalAxis = verticalAxis; - this.horizontalAxis = horizontalAxis; - this.device = device; - - + this.mVerticalAxis = verticalAxis; + this.mHorizontalAxis = horizontalAxis; + this.mInputDevice = device; } public double getAngleRadian(MotionEvent event){ @@ -48,29 +45,18 @@ public class GamepadJoystick { } public double getMagnitude(MotionEvent event){ - float x = Math.abs(event.getAxisValue(horizontalAxis)); - float y = Math.abs(event.getAxisValue(verticalAxis)); + float x = Math.abs(event.getAxisValue(mHorizontalAxis)); + float y = Math.abs(event.getAxisValue(mVerticalAxis)); return MathUtils.dist(0,0, x, y); } public float getVerticalAxis(MotionEvent event){ - return applyDeadzone(event, verticalAxis); + return applyDeadzone(event, mVerticalAxis); } public float getHorizontalAxis(MotionEvent event){ - return applyDeadzone(event, horizontalAxis); - } - - private float applyDeadzone(MotionEvent event, int axis){ - //This piece of code also modifies the value - //to make it seem like there was no deadzone in the first place - - double magnitude = getMagnitude(event); - float deadzone = getDeadzone(); - if (magnitude < deadzone) return 0; - - return (float) ( (event.getAxisValue(axis) / magnitude) * ((magnitude - deadzone) / (1 - deadzone)) ); + return applyDeadzone(event, mHorizontalAxis); } public static boolean isJoystickEvent(MotionEvent event){ @@ -91,9 +77,20 @@ public class GamepadJoystick { */ public float getDeadzone() { try{ - return Math.max(device.getMotionRange(horizontalAxis).getFlat() * 1.9f, 0.2f); + return Math.max(mInputDevice.getMotionRange(mHorizontalAxis).getFlat() * 1.9f, 0.2f); }catch (Exception e){ return 0.2f; } } + + private float applyDeadzone(MotionEvent event, int axis){ + //This piece of code also modifies the value + //to make it seem like there was no deadzone in the first place + + double magnitude = getMagnitude(event); + float deadzone = getDeadzone(); + if (magnitude < deadzone) return 0; + + return (float) ( (event.getAxisValue(axis) / magnitude) * ((magnitude - deadzone) / (1 - deadzone)) ); + } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadMap.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadMap.java index 90ec915b6..ac33e4c8a 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadMap.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/GamepadMap.java @@ -1,6 +1,6 @@ package net.kdt.pojavlaunch.customcontrols.gamepad; -import net.kdt.pojavlaunch.LWJGLGLFWKeycode; +import net.kdt.pojavlaunch.LwjglGlfwKeycode; public class GamepadMap { @@ -76,33 +76,33 @@ public class GamepadMap { public static GamepadMap getDefaultGameMap(){ GamepadMap gameMap = new GamepadMap(); - gameMap.BUTTON_A.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_SPACE}; - gameMap.BUTTON_B.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_Q}; - gameMap.BUTTON_X.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_E}; - gameMap.BUTTON_Y.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_F}; + gameMap.BUTTON_A.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_SPACE}; + gameMap.BUTTON_B.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_Q}; + gameMap.BUTTON_X.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_E}; + gameMap.BUTTON_Y.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_F}; - gameMap.DIRECTION_FORWARD = new int[]{LWJGLGLFWKeycode.GLFW_KEY_W}; - gameMap.DIRECTION_BACKWARD = new int[]{LWJGLGLFWKeycode.GLFW_KEY_S}; - gameMap.DIRECTION_RIGHT = new int[]{LWJGLGLFWKeycode.GLFW_KEY_D}; - gameMap.DIRECTION_LEFT = new int[]{LWJGLGLFWKeycode.GLFW_KEY_A}; + gameMap.DIRECTION_FORWARD = new int[]{LwjglGlfwKeycode.GLFW_KEY_W}; + gameMap.DIRECTION_BACKWARD = new int[]{LwjglGlfwKeycode.GLFW_KEY_S}; + gameMap.DIRECTION_RIGHT = new int[]{LwjglGlfwKeycode.GLFW_KEY_D}; + gameMap.DIRECTION_LEFT = new int[]{LwjglGlfwKeycode.GLFW_KEY_A}; - gameMap.DPAD_UP.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT}; - gameMap.DPAD_DOWN.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_O}; //For mods ? - gameMap.DPAD_RIGHT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_K}; //For mods ? - gameMap.DPAD_LEFT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_J}; //For mods ? + gameMap.DPAD_UP.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT}; + gameMap.DPAD_DOWN.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_O}; //For mods ? + gameMap.DPAD_RIGHT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_K}; //For mods ? + gameMap.DPAD_LEFT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_J}; //For mods ? gameMap.SHOULDER_LEFT.keycodes = new int[]{GamepadMap.MOUSE_SCROLL_UP}; gameMap.SHOULDER_RIGHT.keycodes = new int[]{GamepadMap.MOUSE_SCROLL_DOWN}; - gameMap.TRIGGER_LEFT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT}; - gameMap.TRIGGER_RIGHT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT}; + gameMap.TRIGGER_LEFT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT}; + gameMap.TRIGGER_RIGHT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT}; - gameMap.THUMBSTICK_LEFT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL}; - gameMap.THUMBSTICK_RIGHT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT}; + gameMap.THUMBSTICK_LEFT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_LEFT_CONTROL}; + gameMap.THUMBSTICK_RIGHT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT}; gameMap.THUMBSTICK_RIGHT.isToggleable = true; - gameMap.BUTTON_START.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_ESCAPE}; - gameMap.BUTTON_SELECT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_TAB}; + gameMap.BUTTON_START.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_ESCAPE}; + gameMap.BUTTON_SELECT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_TAB}; return gameMap; } @@ -113,10 +113,10 @@ public class GamepadMap { public static GamepadMap getDefaultMenuMap(){ GamepadMap menuMap = new GamepadMap(); - menuMap.BUTTON_A.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT}; - menuMap.BUTTON_B.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_ESCAPE}; - menuMap.BUTTON_X.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT}; - menuMap.BUTTON_Y.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT}; //Oops, doesn't work since left shift isn't properly applied. + menuMap.BUTTON_A.keycodes = new int[]{LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT}; + menuMap.BUTTON_B.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_ESCAPE}; + menuMap.BUTTON_X.keycodes = new int[]{LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT}; + menuMap.BUTTON_Y.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT, LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT}; //Oops, doesn't work since left shift isn't properly applied. menuMap.DIRECTION_FORWARD = new int[]{GamepadMap.MOUSE_SCROLL_UP, GamepadMap.MOUSE_SCROLL_UP, GamepadMap.MOUSE_SCROLL_UP, GamepadMap.MOUSE_SCROLL_UP, GamepadMap.MOUSE_SCROLL_UP}; menuMap.DIRECTION_BACKWARD = new int[]{GamepadMap.MOUSE_SCROLL_DOWN, GamepadMap.MOUSE_SCROLL_DOWN, GamepadMap.MOUSE_SCROLL_DOWN, GamepadMap.MOUSE_SCROLL_DOWN, GamepadMap.MOUSE_SCROLL_DOWN}; @@ -124,9 +124,9 @@ public class GamepadMap { menuMap.DIRECTION_LEFT = new int[]{}; menuMap.DPAD_UP.keycodes = new int[]{}; - menuMap.DPAD_DOWN.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_O}; //For mods ? - menuMap.DPAD_RIGHT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_K}; //For mods ? - menuMap.DPAD_LEFT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_J}; //For mods ? + menuMap.DPAD_DOWN.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_O}; //For mods ? + menuMap.DPAD_RIGHT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_K}; //For mods ? + menuMap.DPAD_LEFT.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_J}; //For mods ? menuMap.SHOULDER_LEFT.keycodes = new int[]{GamepadMap.MOUSE_SCROLL_UP}; menuMap.SHOULDER_RIGHT.keycodes = new int[]{GamepadMap.MOUSE_SCROLL_DOWN}; @@ -137,7 +137,7 @@ public class GamepadMap { menuMap.THUMBSTICK_LEFT.keycodes = new int[]{}; menuMap.THUMBSTICK_RIGHT.keycodes = new int[]{}; - menuMap.BUTTON_START.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_ESCAPE}; + menuMap.BUTTON_START.keycodes = new int[]{LwjglGlfwKeycode.GLFW_KEY_ESCAPE}; menuMap.BUTTON_SELECT.keycodes = new int[]{}; return menuMap; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/ActionPopupWindow.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/ActionPopupWindow.java index f64d3f8c6..8e48d08bf 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/ActionPopupWindow.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/ActionPopupWindow.java @@ -43,11 +43,11 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe private TextView mDeleteTextView; private TextView mCloneTextView; - private final ControlButton editedButton; + private final ControlButton mEditedButton; public ActionPopupWindow(HandleView handleView, ControlButton button){ super(handleView); - this.editedButton = button; + this.mEditedButton = button; } @Override @@ -97,18 +97,18 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe public void onClick(final View view) { if (view == mEditTextView) { - if(editedButton instanceof ControlSubButton){ - new EditControlSubButtonPopup((ControlSubButton) editedButton); + if(mEditedButton instanceof ControlSubButton){ + new EditControlSubButtonPopup((ControlSubButton) mEditedButton); return; } - if(editedButton instanceof ControlDrawer){ - new EditControlDrawerPopup((ControlDrawer) editedButton); + if(mEditedButton instanceof ControlDrawer){ + new EditControlDrawerPopup((ControlDrawer) mEditedButton); return; } - if(editedButton instanceof ControlButton){ - new EditControlButtonPopup((ControlButton) editedButton); + if(mEditedButton instanceof ControlButton){ + new EditControlButtonPopup((ControlButton) mEditedButton); return; } @@ -121,18 +121,18 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe alertBuilder.setPositiveButton(R.string.global_remove, (p1, p2) -> { ControlLayout layout = ((ControlLayout) mHandleView.mView.getParent()); - if(editedButton instanceof ControlSubButton){ - layout.removeControlSubButton((ControlSubButton) editedButton); + if(mEditedButton instanceof ControlSubButton){ + layout.removeControlSubButton((ControlSubButton) mEditedButton); return; } - if(editedButton instanceof ControlDrawer){ - layout.removeControlDrawer((ControlDrawer) editedButton); + if(mEditedButton instanceof ControlDrawer){ + layout.removeControlDrawer((ControlDrawer) mEditedButton); return; } - if(editedButton instanceof ControlButton){ - layout.removeControlButton((ControlButton) editedButton); + if(mEditedButton instanceof ControlButton){ + layout.removeControlButton((ControlButton) mEditedButton); } layout.removeControlButton(mHandleView.mView); @@ -140,18 +140,18 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe alertBuilder.setNegativeButton(android.R.string.cancel, null); alertBuilder.show(); }else if(view == mCloneTextView) { - if(editedButton instanceof ControlDrawer){ - ControlDrawerData cloneData = new ControlDrawerData(((ControlDrawer)editedButton).getDrawerData()); + if(mEditedButton instanceof ControlDrawer){ + ControlDrawerData cloneData = new ControlDrawerData(((ControlDrawer) mEditedButton).getDrawerData()); cloneData.properties.dynamicX = "0.5 * ${screen_width}"; cloneData.properties.dynamicY = "0.5 * ${screen_height}"; ((ControlLayout) mHandleView.mView.getParent()).addDrawer(cloneData); - }else if(editedButton instanceof ControlSubButton){ - ControlData cloneData = new ControlData(editedButton.getProperties()); + }else if(mEditedButton instanceof ControlSubButton){ + ControlData cloneData = new ControlData(mEditedButton.getProperties()); cloneData.dynamicX = "0.5 * ${screen_width}"; cloneData.dynamicY = "0.5 * ${screen_height}"; - ((ControlLayout) mHandleView.mView.getParent()).addSubButton(((ControlSubButton) editedButton).parentDrawer, cloneData); + ((ControlLayout) mHandleView.mView.getParent()).addSubButton(((ControlSubButton) mEditedButton).parentDrawer, cloneData); }else{ - ControlData cloneData = new ControlData(editedButton.getProperties()); + ControlData cloneData = new ControlData(mEditedButton.getProperties()); cloneData.dynamicX = "0.5 * ${screen_width}"; cloneData.dynamicY = "0.5 * ${screen_height}"; ((ControlLayout) mHandleView.mView.getParent()).addControlButton(cloneData); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/EditControlButtonPopup.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/EditControlButtonPopup.java index 6b4071bb3..18c7d7c1a 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/EditControlButtonPopup.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/EditControlButtonPopup.java @@ -1,6 +1,5 @@ package net.kdt.pojavlaunch.customcontrols.handleview; -import android.app.Dialog; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; @@ -8,7 +7,6 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.ArrayAdapter; import android.widget.CheckBox; -import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageButton; import android.widget.SeekBar; @@ -29,103 +27,103 @@ import static net.kdt.pojavlaunch.customcontrols.handleview.ActionPopupWindow.se public class EditControlButtonPopup { - protected AlertDialog dialog; - protected View v; - protected AlertDialog.Builder builder; + protected AlertDialog mDialog; + protected View mRootView; + protected AlertDialog.Builder mBuilder; - protected EditText editName; - protected Spinner[] spinnersKeycode; + protected EditText mNameEditText; + protected Spinner[] mKeycodeSpinners; - protected CheckBox checkToggle; - protected CheckBox checkPassThrough; - protected CheckBox checkBoxSwipeable; - protected CheckBox checkDynamicPosition; + protected CheckBox mToggleCheckbox; + protected CheckBox mPassthroughCheckbox; + protected CheckBox mSwipeableCheckbox; + protected CheckBox mDynamicPositionCheckbox; - protected EditText editWidth; - protected EditText editHeight; - protected EditText editDynamicX; - protected EditText editDynamicY; + protected EditText mWidthEditText; + protected EditText mHeightEditText; + protected EditText mDynamicXEditText; + protected EditText mDynamicYEditText; - protected SeekBar seekBarOpacity; - protected SeekBar seekBarCornerRadius; - protected SeekBar seekBarStrokeWidth; + protected SeekBar mOpacitySeekbar; + protected SeekBar mCornerRadiusSeekbar; + protected SeekBar mStrokeWidthSeekbar; - protected ImageButton buttonBackgroundColor; - protected ImageButton buttonStrokeColor; + protected ImageButton mBackgroundColorButton; + protected ImageButton mStrokeColorButton; - protected TextView textOpacity; - protected TextView textCornerRadius; - protected TextView textStrokeWidth; - protected TextView textStrokeColor; + protected TextView mOpacityTextView; + protected TextView mCornerRadiusTextView; + protected TextView mStrokeWidthTextView; + protected TextView mStrokeColorTextView; - protected final ControlButton button; - protected final ControlData properties; + protected final ControlButton mControlButton; + protected final ControlData mProperties; - protected ArrayAdapter adapter; - protected String[] specialArr; + protected ArrayAdapter mAdapter; + protected String[] mSpecialArray; public EditControlButtonPopup(ControlButton button){ - this.button = button; - this.properties = button.getProperties(); + this.mControlButton = button; + this.mProperties = button.getProperties(); initializeEditDialog(button.getContext()); //Create the finalized dialog - dialog = builder.create(); - dialog.setOnShowListener(dialogInterface -> setEditDialogValues()); + mDialog = mBuilder.create(); + mDialog.setOnShowListener(dialogInterface -> setEditDialogValues()); - dialog.show(); + mDialog.show(); } protected void initializeEditDialog(Context ctx){ //Create the editing dialog LayoutInflater layoutInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - v = layoutInflater.inflate(R.layout.control_button_setting,null); + mRootView = layoutInflater.inflate(R.layout.dialog_control_button_setting,null); - builder = new AlertDialog.Builder(ctx); - builder.setTitle(ctx.getResources().getString(R.string.customctrl_edit, properties.name)); - builder.setView(v); + mBuilder = new AlertDialog.Builder(ctx); + mBuilder.setTitle(ctx.getResources().getString(R.string.customctrl_edit, mProperties.name)); + mBuilder.setView(mRootView); //Linking a lot of stuff - editName = v.findViewById(R.id.editName_editText); + mNameEditText = mRootView.findViewById(R.id.editName_editText); - spinnersKeycode = new Spinner[]{ - v.findViewById(R.id.editMapping_spinner_1), - v.findViewById(R.id.editMapping_spinner_2), - v.findViewById(R.id.editMapping_spinner_3), - v.findViewById(R.id.editMapping_spinner_4) + mKeycodeSpinners = new Spinner[]{ + mRootView.findViewById(R.id.editMapping_spinner_1), + mRootView.findViewById(R.id.editMapping_spinner_2), + mRootView.findViewById(R.id.editMapping_spinner_3), + mRootView.findViewById(R.id.editMapping_spinner_4) }; - checkToggle = v.findViewById(R.id.checkboxToggle); - checkPassThrough = v.findViewById(R.id.checkboxPassThrough); - checkBoxSwipeable = v.findViewById(R.id.checkboxSwipeable); + mToggleCheckbox = mRootView.findViewById(R.id.checkboxToggle); + mPassthroughCheckbox = mRootView.findViewById(R.id.checkboxPassThrough); + mSwipeableCheckbox = mRootView.findViewById(R.id.checkboxSwipeable); - editWidth = v.findViewById(R.id.editSize_editTextX); - editHeight = v.findViewById(R.id.editSize_editTextY); + mWidthEditText = mRootView.findViewById(R.id.editSize_editTextX); + mHeightEditText = mRootView.findViewById(R.id.editSize_editTextY); - editDynamicX = v.findViewById(R.id.editDynamicPositionX_editText); - editDynamicY = v.findViewById(R.id.editDynamicPositionY_editText); + mDynamicXEditText = mRootView.findViewById(R.id.editDynamicPositionX_editText); + mDynamicYEditText = mRootView.findViewById(R.id.editDynamicPositionY_editText); - seekBarOpacity = v.findViewById(R.id.editButtonOpacity_seekbar); - seekBarCornerRadius = v.findViewById(R.id.editCornerRadius_seekbar); - seekBarStrokeWidth = v.findViewById(R.id.editStrokeWidth_seekbar); + mOpacitySeekbar = mRootView.findViewById(R.id.editButtonOpacity_seekbar); + mCornerRadiusSeekbar = mRootView.findViewById(R.id.editCornerRadius_seekbar); + mStrokeWidthSeekbar = mRootView.findViewById(R.id.editStrokeWidth_seekbar); SeekBar.OnSeekBarChangeListener changeListener = new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { - if(seekBar.equals(seekBarCornerRadius)) { - setPercentageText(textCornerRadius, i); + if(seekBar.equals(mCornerRadiusSeekbar)) { + setPercentageText(mCornerRadiusTextView, i); return; } - if(seekBar.equals(seekBarOpacity)) { - setPercentageText(textOpacity, i); + if(seekBar.equals(mOpacitySeekbar)) { + setPercentageText(mOpacityTextView, i); return; } - if(seekBar.equals(seekBarStrokeWidth)) { - setPercentageText(textStrokeWidth, i); - textStrokeColor.setVisibility(i == 0 ? View.GONE : View.VISIBLE); + if(seekBar.equals(mStrokeWidthSeekbar)) { + setPercentageText(mStrokeWidthTextView, i); + mStrokeColorTextView.setVisibility(i == 0 ? View.GONE : View.VISIBLE); } } @@ -136,43 +134,43 @@ public class EditControlButtonPopup { }; //Add listeners, too bad I don't need all the methods - seekBarOpacity.setOnSeekBarChangeListener(changeListener); - seekBarCornerRadius.setOnSeekBarChangeListener(changeListener); - seekBarStrokeWidth.setOnSeekBarChangeListener(changeListener); + mOpacitySeekbar.setOnSeekBarChangeListener(changeListener); + mCornerRadiusSeekbar.setOnSeekBarChangeListener(changeListener); + mStrokeWidthSeekbar.setOnSeekBarChangeListener(changeListener); - buttonBackgroundColor = v.findViewById(R.id.editBackgroundColor_imageButton); - buttonStrokeColor = v.findViewById(R.id.editStrokeColor_imageButton); + mBackgroundColorButton = mRootView.findViewById(R.id.editBackgroundColor_imageButton); + mStrokeColorButton = mRootView.findViewById(R.id.editStrokeColor_imageButton); - textOpacity = v.findViewById(R.id.editButtonOpacity_textView_percent); - textCornerRadius = v.findViewById(R.id.editCornerRadius_textView_percent); - textStrokeWidth = v.findViewById(R.id.editStrokeWidth_textView_percent); - textStrokeColor = v.findViewById(R.id.editStrokeColor_textView); + mOpacityTextView = mRootView.findViewById(R.id.editButtonOpacity_textView_percent); + mCornerRadiusTextView = mRootView.findViewById(R.id.editCornerRadius_textView_percent); + mStrokeWidthTextView = mRootView.findViewById(R.id.editStrokeWidth_textView_percent); + mStrokeColorTextView = mRootView.findViewById(R.id.editStrokeColor_textView); - checkDynamicPosition = v.findViewById(R.id.checkboxDynamicPosition); - checkDynamicPosition.setOnCheckedChangeListener((btn, checked) -> { - editDynamicX.setEnabled(checked); - editDynamicY.setEnabled(checked); + mDynamicPositionCheckbox = mRootView.findViewById(R.id.checkboxDynamicPosition); + mDynamicPositionCheckbox.setOnCheckedChangeListener((btn, checked) -> { + mDynamicXEditText.setEnabled(checked); + mDynamicYEditText.setEnabled(checked); }); //Initialize adapter for keycodes - adapter = new ArrayAdapter<>(ctx, android.R.layout.simple_spinner_item); + mAdapter = new ArrayAdapter<>(ctx, android.R.layout.simple_spinner_item); String[] oldSpecialArr = ControlData.buildSpecialButtonArray(); - specialArr = new String[oldSpecialArr.length]; - for (int i = 0; i < specialArr.length; i++) { - specialArr[i] = "SPECIAL_" + oldSpecialArr[specialArr.length - i - 1]; + mSpecialArray = new String[oldSpecialArr.length]; + for (int i = 0; i < mSpecialArray.length; i++) { + mSpecialArray[i] = "SPECIAL_" + oldSpecialArr[mSpecialArray.length - i - 1]; } - adapter.addAll(specialArr); - adapter.addAll(EfficientAndroidLWJGLKeycode.generateKeyName()); - adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice); + mAdapter.addAll(mSpecialArray); + mAdapter.addAll(EfficientAndroidLWJGLKeycode.generateKeyName()); + mAdapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice); - for (Spinner spinner : spinnersKeycode) { - spinner.setAdapter(adapter); + for (Spinner spinner : mKeycodeSpinners) { + spinner.setAdapter(mAdapter); } //Set color imageButton behavior - buttonBackgroundColor.setOnClickListener(view -> ActionPopupWindow.showColorPicker(ctx, "Edit background color", true, buttonBackgroundColor)); - buttonStrokeColor.setOnClickListener(view -> ActionPopupWindow.showColorPicker(ctx, "Edit stroke color", false, buttonStrokeColor)); + mBackgroundColorButton.setOnClickListener(view -> ActionPopupWindow.showColorPicker(ctx, "Edit background color", true, mBackgroundColorButton)); + mStrokeColorButton.setOnClickListener(view -> ActionPopupWindow.showColorPicker(ctx, "Edit stroke color", false, mStrokeColorButton)); //Set dialog buttons behavior @@ -187,34 +185,34 @@ public class EditControlButtonPopup { protected void setupDialogButtons(){ //Set dialog buttons behavior - builder.setPositiveButton(android.R.string.ok, (dialogInterface1, i) -> { - if(!hasPropertiesErrors(dialog.getContext())){ + mBuilder.setPositiveButton(android.R.string.ok, (dialogInterface1, i) -> { + if(!hasPropertiesErrors(mDialog.getContext())){ saveProperties(); } }); - builder.setNegativeButton(android.R.string.cancel, null); + mBuilder.setNegativeButton(android.R.string.cancel, null); } protected void hideUselessViews(){ - (v.findViewById(R.id.editOrientation_textView)).setVisibility(View.GONE); + (mRootView.findViewById(R.id.editOrientation_textView)).setVisibility(View.GONE); - (v.findViewById(R.id.editDynamicPositionX_textView)).setVisibility(View.GONE); - (v.findViewById(R.id.editDynamicPositionY_textView)).setVisibility(View.GONE); - editDynamicX.setVisibility(View.GONE); - editDynamicY.setVisibility(View.GONE); + (mRootView.findViewById(R.id.editDynamicPositionX_textView)).setVisibility(View.GONE); + (mRootView.findViewById(R.id.editDynamicPositionY_textView)).setVisibility(View.GONE); + mDynamicXEditText.setVisibility(View.GONE); + mDynamicYEditText.setVisibility(View.GONE); //Hide the color choice if the width is 0. - textStrokeColor.setVisibility(properties.strokeWidth == 0 ? View.GONE : View.VISIBLE); + mStrokeColorTextView.setVisibility(mProperties.strokeWidth == 0 ? View.GONE : View.VISIBLE); } protected void defineDynamicCheckChange(){ - checkDynamicPosition.setOnCheckedChangeListener((compoundButton, b) -> { + mDynamicPositionCheckbox.setOnCheckedChangeListener((compoundButton, b) -> { int visibility = b ? View.VISIBLE : View.GONE; - (v.findViewById(R.id.editDynamicPositionX_textView)).setVisibility(visibility); - (v.findViewById(R.id.editDynamicPositionY_textView)).setVisibility(visibility); - editDynamicX.setVisibility(visibility); - editDynamicY.setVisibility(visibility); + (mRootView.findViewById(R.id.editDynamicPositionX_textView)).setVisibility(visibility); + (mRootView.findViewById(R.id.editDynamicPositionY_textView)).setVisibility(visibility); + mDynamicXEditText.setVisibility(visibility); + mDynamicYEditText.setVisibility(visibility); }); } @@ -226,65 +224,65 @@ public class EditControlButtonPopup { .size((int) Tools.dpToPx(20)) .build(); - buttonBackgroundColor.setBackground(drawable); - buttonStrokeColor.setBackground(drawable); + mBackgroundColorButton.setBackground(drawable); + mStrokeColorButton.setBackground(drawable); } protected void setEditDialogValues(){ - editName.setText(properties.name); + mNameEditText.setText(mProperties.name); - checkToggle.setChecked(properties.isToggle); - checkPassThrough.setChecked(properties.passThruEnabled); - checkBoxSwipeable.setChecked(properties.isSwipeable); + mToggleCheckbox.setChecked(mProperties.isToggle); + mPassthroughCheckbox.setChecked(mProperties.passThruEnabled); + mSwipeableCheckbox.setChecked(mProperties.isSwipeable); - editWidth.setText(Float.toString(properties.getWidth())); - editHeight.setText(Float.toString(properties.getHeight())); + mWidthEditText.setText(Float.toString(mProperties.getWidth())); + mHeightEditText.setText(Float.toString(mProperties.getHeight())); - editDynamicX.setEnabled(properties.isDynamicBtn); - editDynamicY.setEnabled(properties.isDynamicBtn); - editDynamicX.setText(properties.dynamicX); + mDynamicXEditText.setEnabled(mProperties.isDynamicBtn); + mDynamicYEditText.setEnabled(mProperties.isDynamicBtn); + mDynamicXEditText.setText(mProperties.dynamicX); - editDynamicY.setText(properties.dynamicY); + mDynamicYEditText.setText(mProperties.dynamicY); - seekBarOpacity.setProgress((int) (properties.opacity*100)); - seekBarStrokeWidth.setProgress(properties.strokeWidth); - seekBarCornerRadius.setProgress((int)properties.cornerRadius); + mOpacitySeekbar.setProgress((int) (mProperties.opacity*100)); + mStrokeWidthSeekbar.setProgress(mProperties.strokeWidth); + mCornerRadiusSeekbar.setProgress((int) mProperties.cornerRadius); - buttonBackgroundColor.setImageDrawable(new ColorDrawable(properties.bgColor)); - buttonStrokeColor.setImageDrawable(new ColorDrawable(properties.strokeColor)); + mBackgroundColorButton.setImageDrawable(new ColorDrawable(mProperties.bgColor)); + mStrokeColorButton.setImageDrawable(new ColorDrawable(mProperties.strokeColor)); - setPercentageText(textCornerRadius,seekBarCornerRadius.getProgress()); - setPercentageText(textOpacity,seekBarOpacity.getProgress()); - setPercentageText(textStrokeWidth,seekBarStrokeWidth.getProgress()); + setPercentageText(mCornerRadiusTextView, mCornerRadiusSeekbar.getProgress()); + setPercentageText(mOpacityTextView, mOpacitySeekbar.getProgress()); + setPercentageText(mStrokeWidthTextView, mStrokeWidthSeekbar.getProgress()); - checkDynamicPosition.setChecked(properties.isDynamicBtn); + mDynamicPositionCheckbox.setChecked(mProperties.isDynamicBtn); - for(int i=0; i< properties.keycodes.length; i++){ - if (properties.keycodes[i] < 0) { - spinnersKeycode[i].setSelection(properties.keycodes[i] + specialArr.length); + for(int i = 0; i< mProperties.keycodes.length; i++){ + if (mProperties.keycodes[i] < 0) { + mKeycodeSpinners[i].setSelection(mProperties.keycodes[i] + mSpecialArray.length); } else { - spinnersKeycode[i].setSelection(EfficientAndroidLWJGLKeycode.getIndexByValue(properties.keycodes[i]) + specialArr.length); + mKeycodeSpinners[i].setSelection(EfficientAndroidLWJGLKeycode.getIndexByValue(mProperties.keycodes[i]) + mSpecialArray.length); } } } protected boolean hasPropertiesErrors(Context ctx){ - if (editName.getText().toString().isEmpty()) { - editName.setError(ctx.getResources().getString(R.string.global_error_field_empty)); + if (mNameEditText.getText().toString().isEmpty()) { + mNameEditText.setError(ctx.getResources().getString(R.string.global_error_field_empty)); return true; } - if (properties.isDynamicBtn) { + if (mProperties.isDynamicBtn) { int errorAt = 0; try { - properties.insertDynamicPos(editDynamicX.getText().toString()); + mProperties.insertDynamicPos(mDynamicXEditText.getText().toString()); errorAt = 1; - properties.insertDynamicPos(editDynamicY.getText().toString()); + mProperties.insertDynamicPos(mDynamicYEditText.getText().toString()); } catch (Throwable th) { - (errorAt == 0 ? editDynamicX : editDynamicY).setError(th.getMessage()); + (errorAt == 0 ? mDynamicXEditText : mDynamicYEditText).setError(th.getMessage()); return true; } @@ -295,36 +293,36 @@ public class EditControlButtonPopup { protected void saveProperties(){ //This method assumes there are no error. - properties.name = editName.getText().toString(); + mProperties.name = mNameEditText.getText().toString(); //Keycodes - for(int i=0; i adapter = new ArrayAdapter<>(ctx, android.R.layout.simple_spinner_item); adapter.addAll(ControlDrawerData.getOrientations()); adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice); - spinnerOrientation.setAdapter(adapter); + mOrientationSpinner.setAdapter(adapter); } @Override protected void setEditDialogValues() { super.setEditDialogValues(); - spinnerOrientation.setSelection(ControlDrawerData.orientationToInt(drawerData.orientation)); + mOrientationSpinner.setSelection(ControlDrawerData.orientationToInt(mDrawerData.orientation)); //Using the dialog to replace the button behavior allows us not to dismiss the window - dialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(v -> { - ControlLayout layout = (ControlLayout) drawer.getParent(); - ControlData controlData = new ControlData(drawerData.properties); + mDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(v -> { + ControlLayout layout = (ControlLayout) mDrawer.getParent(); + ControlData controlData = new ControlData(mDrawerData.properties); controlData.name = "new"; - layout.addSubButton(drawer, controlData); + layout.addSubButton(mDrawer, controlData); - Context ctx = dialog.getContext(); + Context ctx = mDialog.getContext(); Toast.makeText(ctx, ctx.getString(R.string.customctrl_add_subbutton_message, - drawer.getDrawerData().buttonProperties.size()), Toast.LENGTH_SHORT).show(); + mDrawer.getDrawerData().buttonProperties.size()), Toast.LENGTH_SHORT).show(); }); } @@ -78,13 +78,13 @@ public class EditControlDrawerPopup extends EditControlButtonPopup{ protected void setupDialogButtons() { super.setupDialogButtons(); - builder.setNeutralButton(v.getResources().getString(R.string.customctrl_addsubbutton), null); + mBuilder.setNeutralButton(mRootView.getResources().getString(R.string.customctrl_addsubbutton), null); } @Override protected void saveProperties() { - drawerData.orientation = ControlDrawerData.intToOrientation(spinnerOrientation.getSelectedItemPosition()); + mDrawerData.orientation = ControlDrawerData.intToOrientation(mOrientationSpinner.getSelectedItemPosition()); super.saveProperties(); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/EditControlSubButtonPopup.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/EditControlSubButtonPopup.java index 064a5829e..0b0f90e0b 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/EditControlSubButtonPopup.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/EditControlSubButtonPopup.java @@ -14,15 +14,15 @@ public class EditControlSubButtonPopup extends EditControlButtonPopup{ @Override protected void hideUselessViews() { - (v.findViewById(R.id.editSize_textView)).setVisibility(View.GONE); - (v.findViewById(R.id.editOrientation_textView)).setVisibility(View.GONE); + (mRootView.findViewById(R.id.editSize_textView)).setVisibility(View.GONE); + (mRootView.findViewById(R.id.editOrientation_textView)).setVisibility(View.GONE); - checkDynamicPosition.setVisibility(View.GONE); + mDynamicPositionCheckbox.setVisibility(View.GONE); - (v.findViewById(R.id.editDynamicPositionX_textView)).setVisibility(View.GONE); - editDynamicX.setVisibility(View.GONE); + (mRootView.findViewById(R.id.editDynamicPositionX_textView)).setVisibility(View.GONE); + mDynamicXEditText.setVisibility(View.GONE); - (v.findViewById(R.id.editDynamicPositionY_textView)).setVisibility(View.GONE); - editDynamicY.setVisibility(View.GONE); + (mRootView.findViewById(R.id.editDynamicPositionY_textView)).setVisibility(View.GONE); + mDynamicYEditText.setVisibility(View.GONE); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/HandleView.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/HandleView.java index 1378be5db..c8278cadf 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/HandleView.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/HandleView.java @@ -29,10 +29,8 @@ import net.kdt.pojavlaunch.*; import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton; -public abstract class HandleView extends View implements ViewPositionListener, View.OnLongClickListener - { +public abstract class HandleView extends View implements ViewPositionListener, View.OnLongClickListener { protected Drawable mDrawable; - protected Drawable mDrawableLtr; protected Drawable mDrawableRtl; private final PopupWindow mContainer; // Position with respect to the parent TextView @@ -65,12 +63,19 @@ public abstract class HandleView extends View implements ViewPositionListener, V // int mWindowPosX, mWindowPosY; private PositionListener mPositionListener; - public PositionListener getPositionListener() { - if (mPositionListener == null) { - mPositionListener = new PositionListener(mView); - } - return mPositionListener; - } + + // Touch-up filter: number of previous positions remembered + private static final int HISTORY_SIZE = 5; + private static final int TOUCH_UP_FILTER_DELAY_AFTER = 150; + private static final int TOUCH_UP_FILTER_DELAY_BEFORE = 350; + private final long[] mPreviousOffsetsTimes = new long[HISTORY_SIZE]; + private final int[] mPreviousOffsets = new int[HISTORY_SIZE]; + private int mPreviousOffsetIndex = 0; + private int mNumberPreviousOffsets = 0; + + // Addition + private float mDownX, mDownY; + public HandleView(ControlButton view) { super(view.getContext()); @@ -86,8 +91,7 @@ public abstract class HandleView extends View implements ViewPositionListener, V mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); mContainer.setContentView(this); - mDrawableLtr = view.getContext().getDrawable(R.drawable.text_select_handle_left_material); - mDrawableRtl = view.getContext().getDrawable(R.drawable.text_select_handle_right_material); + mDrawableRtl = view.getContext().getDrawable(R.drawable.ic_view_handle); mMinSize = view.getContext().getResources().getDimensionPixelSize(R.dimen.text_handle_min_size); setOnLongClickListener(this); @@ -99,11 +103,103 @@ public abstract class HandleView extends View implements ViewPositionListener, V mIdealVerticalOffset = 0.7f * handleHeight; } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(getPreferredWidth(), getPreferredHeight()); + } + + @Override + protected void onDraw(Canvas c) { + final int drawWidth = mDrawable.getIntrinsicWidth(); + final int left = getHorizontalOffset(); + + mDrawable.setBounds(left, 0, left + drawWidth, mDrawable.getIntrinsicHeight()); + mDrawable.draw(c); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + ViewGroup.LayoutParams params = mView.getLayoutParams(); + + switch (ev.getActionMasked()) { + case MotionEvent.ACTION_DOWN: { + startTouchUpFilter(getCurrentCursorOffset()); + mTouchToWindowOffsetX = ev.getRawX() - mPositionX; + mTouchToWindowOffsetY = ev.getRawY() - mPositionY; + + final PositionListener positionListener = getPositionListener(); + mLastParentX = positionListener.getPositionX(); + mLastParentY = positionListener.getPositionY(); + mIsDragging = true; + + // MOD: Addition + mDownX = ev.getRawX(); + mDownY = ev.getRawY(); + mDownWidth = params.width; + mDownHeight = params.height; + + break; + } + + case MotionEvent.ACTION_MOVE: { + final float rawX = ev.getRawX(); + final float rawY = ev.getRawY(); + + // Vertical hysteresis: vertical down movement tends to snap to ideal offset + final float previousVerticalOffset = mTouchToWindowOffsetY - mLastParentY; + final float currentVerticalOffset = rawY - mPositionY - mLastParentY; + float newVerticalOffset; + if (previousVerticalOffset < mIdealVerticalOffset) { + newVerticalOffset = Math.min(currentVerticalOffset, mIdealVerticalOffset); + newVerticalOffset = Math.max(newVerticalOffset, previousVerticalOffset); + } else { + newVerticalOffset = Math.max(currentVerticalOffset, mIdealVerticalOffset); + newVerticalOffset = Math.min(newVerticalOffset, previousVerticalOffset); + } + mTouchToWindowOffsetY = newVerticalOffset + mLastParentY; + + final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX; + final float newPosY = rawY - mTouchToWindowOffsetY + mTouchOffsetY; + + int newWidth = (int) (mDownWidth + (rawX - mDownX)); + int newHeight = (int) (mDownHeight + (rawY - mDownY)); + + // mDownX = rawX; + // mDownY = rawY; + + params.width = Math.max(50, newWidth); + params.height = Math.max(50, newHeight); + + mView.setLayoutParams(params); + + updatePosition(newPosX, newPosY); + // break; + return true; + } + + case MotionEvent.ACTION_UP: + filterOnTouchUp(); + mIsDragging = false; + break; + + case MotionEvent.ACTION_CANCEL: + mIsDragging = false; + break; + } + return true; + } + + public PositionListener getPositionListener() { + if (mPositionListener == null) { + mPositionListener = new PositionListener(mView); + } + return mPositionListener; + } protected void updateDrawable() { // final int offset = getCurrentCursorOffset(); final boolean isRtlCharAtOffset = true; // mView.getLayout().isRtlCharAt(offset); - mDrawable = isRtlCharAtOffset ? mDrawableRtl : mDrawableLtr; + mDrawable = mDrawableRtl; //isRtlCharAtOffset ? mDrawableRtl : mDrawableLtr; mHotspotX = getHotspotX(mDrawable, isRtlCharAtOffset); mHorizontalGravity = getHorizontalGravity(isRtlCharAtOffset); } @@ -111,14 +207,7 @@ public abstract class HandleView extends View implements ViewPositionListener, V protected abstract int getHotspotX(Drawable drawable, boolean isRtlRun); protected abstract int getHorizontalGravity(boolean isRtlRun); - // Touch-up filter: number of previous positions remembered - private static final int HISTORY_SIZE = 5; - private static final int TOUCH_UP_FILTER_DELAY_AFTER = 150; - private static final int TOUCH_UP_FILTER_DELAY_BEFORE = 350; - private final long[] mPreviousOffsetsTimes = new long[HISTORY_SIZE]; - private final int[] mPreviousOffsets = new int[HISTORY_SIZE]; - private int mPreviousOffsetIndex = 0; - private int mNumberPreviousOffsets = 0; + private void startTouchUpFilter(int offset) { mNumberPreviousOffsets = 0; @@ -152,11 +241,6 @@ public abstract class HandleView extends View implements ViewPositionListener, V return mNumberPreviousOffsets > 1; } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(getPreferredWidth(), getPreferredHeight()); - } - private int getPreferredWidth() { return Math.max(mDrawable.getIntrinsicWidth(), mMinSize); } @@ -283,15 +367,6 @@ public abstract class HandleView extends View implements ViewPositionListener, V } } - @Override - protected void onDraw(Canvas c) { - final int drawWidth = mDrawable.getIntrinsicWidth(); - final int left = getHorizontalOffset(); - - mDrawable.setBounds(left, 0, left + drawWidth, mDrawable.getIntrinsicHeight()); - mDrawable.draw(c); - } - private int getHorizontalOffset() { final int width = getPreferredWidth(); final int drawWidth = mDrawable.getIntrinsicWidth(); @@ -315,81 +390,6 @@ public abstract class HandleView extends View implements ViewPositionListener, V return 0; } - // Addition - private float mDownX, mDownY; - - @Override - public boolean onTouchEvent(MotionEvent ev) { - ViewGroup.LayoutParams params = mView.getLayoutParams(); - - switch (ev.getActionMasked()) { - case MotionEvent.ACTION_DOWN: { - startTouchUpFilter(getCurrentCursorOffset()); - mTouchToWindowOffsetX = ev.getRawX() - mPositionX; - mTouchToWindowOffsetY = ev.getRawY() - mPositionY; - - final PositionListener positionListener = getPositionListener(); - mLastParentX = positionListener.getPositionX(); - mLastParentY = positionListener.getPositionY(); - mIsDragging = true; - - // MOD: Addition - mDownX = ev.getRawX(); - mDownY = ev.getRawY(); - mDownWidth = params.width; - mDownHeight = params.height; - - break; - } - - case MotionEvent.ACTION_MOVE: { - final float rawX = ev.getRawX(); - final float rawY = ev.getRawY(); - - // Vertical hysteresis: vertical down movement tends to snap to ideal offset - final float previousVerticalOffset = mTouchToWindowOffsetY - mLastParentY; - final float currentVerticalOffset = rawY - mPositionY - mLastParentY; - float newVerticalOffset; - if (previousVerticalOffset < mIdealVerticalOffset) { - newVerticalOffset = Math.min(currentVerticalOffset, mIdealVerticalOffset); - newVerticalOffset = Math.max(newVerticalOffset, previousVerticalOffset); - } else { - newVerticalOffset = Math.max(currentVerticalOffset, mIdealVerticalOffset); - newVerticalOffset = Math.min(newVerticalOffset, previousVerticalOffset); - } - mTouchToWindowOffsetY = newVerticalOffset + mLastParentY; - - final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX; - final float newPosY = rawY - mTouchToWindowOffsetY + mTouchOffsetY; - - int newWidth = (int) (mDownWidth + (rawX - mDownX)); - int newHeight = (int) (mDownHeight + (rawY - mDownY)); - - // mDownX = rawX; - // mDownY = rawY; - - params.width = Math.max(50, newWidth); - params.height = Math.max(50, newHeight); - - mView.setLayoutParams(params); - - updatePosition(newPosX, newPosY); - // break; - return true; - } - - case MotionEvent.ACTION_UP: - filterOnTouchUp(); - mIsDragging = false; - break; - - case MotionEvent.ACTION_CANCEL: - mIsDragging = false; - break; - } - return true; - } - public boolean isDragging() { return mIsDragging; } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/SelectionEndHandleView.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/SelectionEndHandleView.java index 489c91bec..ebbb5e64c 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/SelectionEndHandleView.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/SelectionEndHandleView.java @@ -25,8 +25,7 @@ import android.view.*; import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton; -public class SelectionEndHandleView extends HandleView -{ +public class SelectionEndHandleView extends HandleView { public SelectionEndHandleView(ControlButton view) { super(view); } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/ViewPositionListener.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/ViewPositionListener.java index 0dd53f6c2..cf0dda3a2 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/ViewPositionListener.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/handleview/ViewPositionListener.java @@ -20,5 +20,5 @@ package net.kdt.pojavlaunch.customcontrols.handleview; public interface ViewPositionListener { - public void updatePosition(int parentPositionX, int parentPositionY, boolean parentPositionChanged, boolean parentScrolled); + void updatePosition(int parentPositionX, int parentPositionY, boolean parentPositionChanged, boolean parentScrolled); } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/extra/ExtraCore.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/extra/ExtraCore.java index 3e26c24ef..e14ad285f 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/extra/ExtraCore.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/extra/ExtraCore.java @@ -17,24 +17,24 @@ public final class ExtraCore { private ExtraCore(){} // Singleton instance - private static ExtraCore extraCoreSingleton = null; + private static ExtraCore sExtraCoreSingleton = null; // Store the key-value pair - private final Map valueMap = new ConcurrentHashMap<>(); + private final Map mValueMap = new ConcurrentHashMap<>(); // Store what each ExtraListener listen to - private final Map>> listenerMap = new ConcurrentHashMap<>(); + private final Map>> mListenerMap = new ConcurrentHashMap<>(); // All public methods will pass through this one private static ExtraCore getInstance(){ - if(extraCoreSingleton == null){ + if(sExtraCoreSingleton == null){ synchronized(ExtraCore.class){ - if(extraCoreSingleton == null){ - extraCoreSingleton = new ExtraCore(); + if(sExtraCoreSingleton == null){ + sExtraCoreSingleton = new ExtraCore(); } } } - return extraCoreSingleton; + return sExtraCoreSingleton; } /** @@ -45,8 +45,8 @@ public final class ExtraCore { public static void setValue(String key, Object value){ if(value == null || key == null) return; // null values create an NPE on insertion - getInstance().valueMap.put(key, value); - ConcurrentLinkedQueue> extraListenerList = getInstance().listenerMap.get(key); + getInstance().mValueMap.put(key, value); + ConcurrentLinkedQueue> extraListenerList = getInstance().mListenerMap.get(key); if(extraListenerList == null) return; //No listeners for(WeakReference listener : extraListenerList){ if(listener.get() == null){ @@ -63,17 +63,17 @@ public final class ExtraCore { /** @return The value behind the key */ public static Object getValue(String key){ - return getInstance().valueMap.get(key); + return getInstance().mValueMap.get(key); } /** Remove the key and its value from the valueMap */ public static void removeValue(String key){ - getInstance().valueMap.remove(key); + getInstance().mValueMap.remove(key); } /** Remove all values */ public static void removeAllValues(){ - getInstance().valueMap.clear(); + getInstance().mValueMap.clear(); } /** @@ -82,11 +82,11 @@ public final class ExtraCore { * @param listener The ExtraListener to link */ public static void addExtraListener(String key, ExtraListener listener){ - ConcurrentLinkedQueue> listenerList = getInstance().listenerMap.get(key); + ConcurrentLinkedQueue> listenerList = getInstance().mListenerMap.get(key); // Look for new sets if(listenerList == null){ listenerList = new ConcurrentLinkedQueue<>(); - getInstance().listenerMap.put(key, listenerList); + getInstance().mListenerMap.put(key, listenerList); } // This is kinda naive, I should look for duplicates @@ -100,11 +100,11 @@ public final class ExtraCore { * @param listener The ExtraListener to unlink */ public static void removeExtraListenerFromValue(String key, ExtraListener listener){ - ConcurrentLinkedQueue> listenerList = getInstance().listenerMap.get(key); + ConcurrentLinkedQueue> listenerList = getInstance().mListenerMap.get(key); // Look for new sets if(listenerList == null){ listenerList = new ConcurrentLinkedQueue<>(); - getInstance().listenerMap.put(key, listenerList); + getInstance().mListenerMap.put(key, listenerList); } // Removes all occurrences of ExtraListener and all null references @@ -122,11 +122,11 @@ public final class ExtraCore { * @param key The key to which ExtraListener are linked */ public static void removeAllExtraListenersFromValue(String key){ - ConcurrentLinkedQueue> listenerList = getInstance().listenerMap.get(key); + ConcurrentLinkedQueue> listenerList = getInstance().mListenerMap.get(key); // Look for new sets if(listenerList == null){ listenerList = new ConcurrentLinkedQueue<>(); - getInstance().listenerMap.put(key, listenerList); + getInstance().mListenerMap.put(key, listenerList); } listenerList.clear(); @@ -136,7 +136,7 @@ public final class ExtraCore { * Remove all ExtraListeners from listening to any value */ public static void removeAllExtraListeners(){ - getInstance().listenerMap.clear(); + getInstance().mListenerMap.clear(); } } \ No newline at end of file diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ConsoleFragment.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ConsoleFragment.java index df917a536..4dc026e47 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ConsoleFragment.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ConsoleFragment.java @@ -2,6 +2,7 @@ package net.kdt.pojavlaunch.fragments; import android.os.*; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import android.view.*; import android.widget.*; @@ -12,34 +13,33 @@ import android.graphics.*; import androidx.fragment.app.Fragment; -public class ConsoleFragment extends Fragment -{ - public TextView consoleView; - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - super.onCreateView(inflater, container, savedInstanceState); - View view = inflater.inflate(R.layout.lmaintab_consolelog, container, false); +public class ConsoleFragment extends Fragment { + public TextView mConsoleView; - consoleView = (TextView) view.findViewById(R.id.lmaintabconsoleLogTextView); - consoleView.setTypeface(Typeface.MONOSPACE); - consoleView.setHint(this.getText(R.string.main_nolog)); + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + View view = inflater.inflate(R.layout.fragment_console_log, container, false); + + mConsoleView = (TextView) view.findViewById(R.id.lmaintabconsoleLogTextView); + mConsoleView.setTypeface(Typeface.MONOSPACE); + mConsoleView.setHint(this.getText(R.string.main_nolog)); return view; } @Override - public void onResume() - { + public void onResume() { super.onResume(); - consoleView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogTextView); + mConsoleView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogTextView); } public void putLog(String str) { - if (consoleView == null) { - consoleView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogTextView); + if (mConsoleView == null) { + mConsoleView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogTextView); } - consoleView.append(str); + mConsoleView.append(str); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/CrashFragment.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/CrashFragment.java index 4ad687bfc..c555f747f 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/CrashFragment.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/CrashFragment.java @@ -2,7 +2,10 @@ package net.kdt.pojavlaunch.fragments; import android.os.*; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; + +import android.util.Log; import android.view.*; import android.widget.*; import java.io.*; @@ -11,80 +14,76 @@ import net.kdt.pojavlaunch.*; import android.graphics.*; import androidx.fragment.app.Fragment; -public class CrashFragment extends Fragment -{ - public static String lastCrashFile = Tools.DIR_DATA + "/lastcrash.txt"; - - private String crashContent; - private TextView crashView; - - public boolean resetCrashLog = false; - - public static boolean isNewCrash(File crashLog) throws Exception { - String content = Tools.read(crashLog.getAbsolutePath()); - return crashLog != null && content.startsWith("---- Minecraft Crash Report ----"); - } - - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - super.onCreateView(inflater, container, savedInstanceState); - View view = inflater.inflate(R.layout.lmaintab_crashlog, container, false); +public class CrashFragment extends Fragment { + public static String LAST_CRASH_FILE = Tools.DIR_DATA + "/lastcrash.txt"; - return view; - } - - @Override - public void onActivityCreated(Bundle b) - { - super.onActivityCreated(b); - - crashView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogCrashTextView); - crashView.setTypeface(Typeface.MONOSPACE); - crashView.setHint(this.getText(R.string.main_nocrash)); + private TextView mCrashView; + public boolean mResetCrashLog = false; - } - @Override - public void onResume() - { + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + return inflater.inflate(R.layout.fragment_crash_log, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + mCrashView = (TextView) getView().findViewById(R.id.lmaintabconsoleLogCrashTextView); + mCrashView.setTypeface(Typeface.MONOSPACE); + mCrashView.setHint(this.getText(R.string.main_nocrash)); + } + + + @Override + public void onResume(){ super.onResume(); refreshCrashFile(); } - - public void refreshCrashFile() - { + + private void refreshCrashFile() { + // Default text + mCrashView.setText(""); + setLastCrash(""); + + if(mResetCrashLog) return; + + File crashLog = Tools.lastFileModified(Tools.DIR_HOME_CRASH); + String lastCrash = getLastCrash(); + String crashContent; try { - if(!resetCrashLog){ - File crashLog = Tools.lastFileModified(Tools.DIR_HOME_CRASH); - String lastCrash = getLastCrash(); - if (isNewCrash(crashLog)) { - crashContent = Tools.read(crashLog.getAbsolutePath()); - Tools.write(crashLog.getAbsolutePath(), "\n" + crashContent); - setLastCrash(crashLog.getAbsolutePath()); - crashView.setText(crashContent); - } else if(!lastCrash.isEmpty()) { - crashContent = Tools.read(lastCrash); - crashView.setText(crashContent); - } else throw new Exception(); - } else throw new Exception(); - } catch (Exception e) { - // Can't find crash or no NEW crashes - crashView.setText(""/*Log.getStackTraceString(e)*/); - setLastCrash(""); + if (isNewCrash(crashLog)) { + crashContent = Tools.read(crashLog.getAbsolutePath()); + Tools.write(crashLog.getAbsolutePath(), "\n" + crashContent); + setLastCrash(crashLog.getAbsolutePath()); + mCrashView.setText(crashContent); + } else if(!lastCrash.isEmpty()) { + crashContent = Tools.read(lastCrash); + mCrashView.setText(crashContent); + } + }catch (IOException ioException){ + Log.e("CrashFragment", ioException.toString()); } } - - public void setLastCrash(String newValue) { + + private static boolean isNewCrash(File crashLog) throws IOException { + String content = Tools.read(crashLog.getAbsolutePath()); + return crashLog != null && content.startsWith("---- Minecraft Crash Report ----"); + } + + private void setLastCrash(String newValue) { try { - Tools.write(lastCrashFile, newValue); - } catch (Throwable th) { - throw new RuntimeException(th); + Tools.write(LAST_CRASH_FILE, newValue); + } catch (IOException ioException) { + throw new RuntimeException(ioException); } } - - public String getLastCrash() { + + private String getLastCrash() { try { - return Tools.read(lastCrashFile); - } catch (Throwable th) { + return Tools.read(LAST_CRASH_FILE); + } catch (IOException ioException) { return ""; } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/LauncherFragment.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/LauncherFragment.java index c0a3be4a5..c0871d3c8 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/LauncherFragment.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/LauncherFragment.java @@ -4,12 +4,12 @@ import android.content.Intent; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; + +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.fragment.app.Fragment; -import android.os.Handler; -import android.os.Looper; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -25,74 +25,45 @@ import net.kdt.pojavlaunch.prefs.LauncherPreferences; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.MalformedURLException; import java.net.URL; -import java.util.HashMap; import java.util.Locale; -import java.util.Objects; -public class LauncherFragment extends Fragment -{ - private WebView webNews; - private View view; - private Thread validUrlSelectorThread; - private String validChangelog = "/changelog.html"; - private Handler mainHandler = new Handler(Looper.getMainLooper()); - private boolean interruptLoad = false; - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - super.onCreateView(inflater, container, savedInstanceState); - view = inflater.inflate(R.layout.lmaintab_news, container, false); - return view; - } - public void selectValidUrl() { - String lang = LauncherPreferences.PREF_LANGUAGE; - if(lang.equals("default")) lang = Locale.getDefault().getLanguage(); - final String localizedUrl = "/changelog-"+lang+".html"; - if(!tryUrl(Tools.URL_HOME+localizedUrl)) return; - else { - mainHandler.post(()->{ - interruptLoad = true; - validChangelog = localizedUrl; - webNews.loadUrl(Tools.URL_HOME+validChangelog); - }); - } - } - public boolean tryUrl(String url) { - Log.i("ChangelogLocale","Trying localized url: "+url); - try { - HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); - conn.connect(); - Log.i("ChangelogLocale","Code: "+conn.getResponseCode()); - return ("" + conn.getResponseCode()).startsWith("2"); - }catch (IOException e) { - e.printStackTrace(); - return false; - } - } +public class LauncherFragment extends Fragment { + + private WebView mNewsWebview; + private View mRootView; + private Thread mValidUrlSelectorThread; + private String mValidChangelog = "/changelog.html"; + private boolean mInterruptLoad = false; + @Override - public void onActivityCreated(Bundle p1) - { - super.onActivityCreated(p1); - mainHandler = new Handler(Looper.myLooper()); - webNews = (WebView) getView().findViewById(R.id.lmaintabnewsNewsView); - webNews.setWebViewClient(new WebViewClient(){ + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + mRootView = inflater.inflate(R.layout.fragment_news, container, false); + return mRootView; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + mNewsWebview = (WebView) getView().findViewById(R.id.lmaintabnewsNewsView); + mNewsWebview.setWebViewClient(new WebViewClient(){ // API < 23 @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Log.i("WebNews",failingUrl + ": "+description); - if(webNews != null){ - if(validUrlSelectorThread.isAlive()) validUrlSelectorThread.interrupt(); - removeWebView(); - //Change the background to match the other pages. - //We change it only when the webView is removed to avoid huge overdraw. - LauncherFragment.this.view.setBackgroundColor(Color.parseColor("#44000000")); - } + if(mNewsWebview == null) return; + + if(mValidUrlSelectorThread.isAlive()) mValidUrlSelectorThread.interrupt(); + removeWebView(); + //Change the background to match the other pages. + //We change it only when the webView is removed to avoid huge overdraw. + LauncherFragment.this.mRootView.setBackgroundColor(Color.parseColor("#44000000")); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - if(!url.equals(Tools.URL_HOME + validChangelog)){ + if(!url.equals(Tools.URL_HOME + mValidChangelog)){ Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(i); return true; @@ -104,17 +75,17 @@ public class LauncherFragment extends Fragment @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { Log.i("WebNews",error.getDescription()+""); - if(webNews != null){ - if(validUrlSelectorThread.isAlive()) validUrlSelectorThread.interrupt(); - removeWebView(); - LauncherFragment.this.view.setBackgroundColor(Color.parseColor("#44000000")); - } + if(mNewsWebview == null) return; + + if(mValidUrlSelectorThread.isAlive()) mValidUrlSelectorThread.interrupt(); + removeWebView(); + LauncherFragment.this.mRootView.setBackgroundColor(Color.parseColor("#44000000")); } @RequiresApi(23) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { - if(!request.getUrl().toString().equals(Tools.URL_HOME + validChangelog)){ + if(!request.getUrl().toString().equals(Tools.URL_HOME + mValidChangelog)){ Intent i = new Intent(Intent.ACTION_VIEW, request.getUrl()); startActivity(i); return true; @@ -122,36 +93,64 @@ public class LauncherFragment extends Fragment return false; } }); - webNews.clearCache(true); - webNews.getSettings().setJavaScriptEnabled(true); - validUrlSelectorThread = new Thread(this::selectValidUrl); - validUrlSelectorThread.start(); - if(!interruptLoad)webNews.loadUrl(Tools.URL_HOME + validChangelog); + + mNewsWebview.clearCache(true); + mNewsWebview.getSettings().setJavaScriptEnabled(true); + mValidUrlSelectorThread = new Thread(this::selectValidUrl); + mValidUrlSelectorThread.start(); + if(!mInterruptLoad) mNewsWebview.loadUrl(Tools.URL_HOME + mValidChangelog); + } + + private void selectValidUrl() { + String lang = LauncherPreferences.PREF_LANGUAGE; + if(lang.equals("default")) lang = Locale.getDefault().getLanguage(); + final String localizedUrl = "/changelog-" + lang + ".html"; + + if(!tryUrl(Tools.URL_HOME+localizedUrl)) return; + + requireActivity().runOnUiThread(() -> { + mInterruptLoad = true; + mValidChangelog = localizedUrl; + mNewsWebview.loadUrl(Tools.URL_HOME + mValidChangelog); + }); + } + + private boolean tryUrl(String url) { + Log.i("ChangelogLocale","Trying localized url: "+url); + try { + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.connect(); + Log.i("ChangelogLocale","Code: "+conn.getResponseCode()); + return ("" + conn.getResponseCode()).startsWith("2"); + }catch (IOException e) { + e.printStackTrace(); + return false; + } } private void removeWebView() { //Removing the parent which contain the webView crashes the viewPager. //So I just try to "minimize" its impact on memory instead - webNews.clearHistory(); - webNews.clearCache(true); + mNewsWebview.clearHistory(); + mNewsWebview.clearCache(true); // Loading a blank page is optional, but will ensure that the WebView isn't doing anything when you destroy it. - webNews.loadUrl("about:blank"); + mNewsWebview.loadUrl("about:blank"); - webNews.onPause(); - webNews.removeAllViews(); - webNews.destroyDrawingCache(); + mNewsWebview.onPause(); + mNewsWebview.removeAllViews(); + mNewsWebview.destroyDrawingCache(); // make sure to call webNews.resumeTimers(). - webNews.pauseTimers(); + mNewsWebview.pauseTimers(); - webNews.setVisibility(View.GONE); + mNewsWebview.setVisibility(View.GONE); - webNews.destroy(); + mNewsWebview.destroy(); // Null out the reference so that you don't end up re-using it. - webNews = null; + mNewsWebview = null; } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java index e00eb8e45..7e0bdbfc2 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java @@ -14,31 +14,33 @@ import net.kdt.pojavlaunch.R; public class MultiRTConfigDialog { public static final int MULTIRT_PICK_RUNTIME = 2048; public static final int MULTIRT_PICK_RUNTIME_STARTUP = 2049; - public AlertDialog dialog; - public RecyclerView dialogView; - public void prepare(BaseLauncherActivity ctx) { - AlertDialog.Builder builder = new AlertDialog.Builder(ctx); + public AlertDialog mDialog; + public RecyclerView mDialogView; + + public void prepare(BaseLauncherActivity activity) { + mDialogView = new RecyclerView(activity); + mDialogView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)); + mDialogView.setAdapter(new RTRecyclerViewAdapter(this)); + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(R.string.multirt_config_title); - dialogView = new RecyclerView(ctx); - LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ctx); - linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); - dialogView.setLayoutManager(linearLayoutManager); - dialogView.setAdapter(new RTRecyclerViewAdapter(this)); - builder.setView(dialogView); - builder.setPositiveButton(R.string.multirt_config_add, (dialog, which) -> openRuntimeSelector(ctx,MULTIRT_PICK_RUNTIME)); + builder.setView(mDialogView); + builder.setPositiveButton(R.string.multirt_config_add, (dialog, which) -> openRuntimeSelector(activity,MULTIRT_PICK_RUNTIME)); builder.setNegativeButton(R.string.mcn_exit_call, (dialog, which) -> dialog.cancel()); - dialog = builder.create(); + mDialog = builder.create(); } + public void refresh() { - RecyclerView.Adapter adapter = dialogView.getAdapter(); - if(adapter != null)dialogView.getAdapter().notifyDataSetChanged(); + RecyclerView.Adapter adapter = mDialogView.getAdapter(); + if(adapter != null) mDialogView.getAdapter().notifyDataSetChanged(); } - public static void openRuntimeSelector(Activity ctx, int code) { + + public static void openRuntimeSelector(Activity activity, int code) { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("xz"); if(mimeType == null) mimeType = "*/*"; intent.setType(mimeType); - ctx.startActivityForResult(intent,code); + activity.startActivityForResult(intent,code); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java index 3cf4ab32c..38ec39f98 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java @@ -2,6 +2,7 @@ package net.kdt.pojavlaunch.multirt; import android.content.Context; import android.system.Os; +import android.util.Log; import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.Tools; @@ -22,135 +23,102 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Objects; public class MultiRTUtils { - public static HashMap cache = new HashMap<>(); - public static class Runtime { - public Runtime(String name) { - this.name = name; - } - public String name; - public String versionString; - public String arch; - public int javaVersion; + public interface RuntimeProgressReporter { + void reportStringProgress(int resId, Object ... stuff); + } + + private static final HashMap sCache = new HashMap<>(); + + private static final File RUNTIME_FOLDER = new File(Tools.MULTIRT_HOME); + private static final String JAVA_VERSION_STR = "JAVA_VERSION=\""; + private static final String OS_ARCH_STR = "OS_ARCH=\""; - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Runtime runtime = (Runtime) o; - return name.equals(runtime.name); - } - @Override - public int hashCode() { - return Objects.hash(name); - } - } - public static interface ProgressReporterThingy { - void reportStringProgress(int resid, Object ... stuff); - } - private static final File runtimeFolder = new File(Tools.MULTIRT_HOME); - private static final String JAVA_VERSION_str = "JAVA_VERSION=\""; - private static final String OS_ARCH_str = "OS_ARCH=\""; public static List getRuntimes() { - if(!runtimeFolder.exists()) runtimeFolder.mkdirs(); - ArrayList ret = new ArrayList<>(); + if(!RUNTIME_FOLDER.exists()) RUNTIME_FOLDER.mkdirs(); + + ArrayList runtimes = new ArrayList<>(); System.out.println("Fetch runtime list"); - for(File f : runtimeFolder.listFiles()) { - ret.add(read(f.getName())); + for(File f : RUNTIME_FOLDER.listFiles()) { + runtimes.add(read(f.getName())); } - return ret; + return runtimes; } - public static String getExactJREName(int majorVersion) { + + public static String getExactJreName(int majorVersion) { List runtimes = getRuntimes(); - for(Runtime r : runtimes) { - if(r.javaVersion == majorVersion) { - return r.name; - } - } + for(Runtime r : runtimes) + if(r.javaVersion == majorVersion)return r.name; + return null; } - public static String getNearestJREName(int majorVersion) { + + public static String getNearestJreName(int majorVersion) { List runtimes = getRuntimes(); int diff_factor = Integer.MAX_VALUE; String result = null; for(Runtime r : runtimes) { - if(r.javaVersion >= majorVersion) { // lower - not useful - int currentFactor = r.javaVersion - majorVersion; - if(diff_factor > currentFactor) { - result = r.name; - diff_factor = currentFactor; - } + if(r.javaVersion < majorVersion) continue; // lower - not useful + + int currentFactor = r.javaVersion - majorVersion; + if(diff_factor > currentFactor) { + result = r.name; + diff_factor = currentFactor; } } + return result; } - public static void installRuntimeNamed(InputStream runtimeInputStream, String name, ProgressReporterThingy thingy) throws IOException { - File dest = new File(runtimeFolder,"/"+name); + + public static void installRuntimeNamed(InputStream runtimeInputStream, String name, RuntimeProgressReporter progressReporter) throws IOException { + File dest = new File(RUNTIME_FOLDER,"/"+name); File tmp = new File(dest,"temporary"); if(dest.exists()) FileUtils.deleteDirectory(dest); dest.mkdirs(); FileOutputStream fos = new FileOutputStream(tmp); - thingy.reportStringProgress(R.string.multirt_progress_caching); + progressReporter.reportStringProgress(R.string.multirt_progress_caching); IOUtils.copy(runtimeInputStream,fos); fos.close(); runtimeInputStream.close(); - uncompressTarXZ(tmp,dest,thingy); + uncompressTarXZ(tmp,dest,progressReporter); tmp.delete(); read(name); } - private static void __installRuntimeNamed__NoRM(InputStream runtimeInputStream, File dest, ProgressReporterThingy thingy) throws IOException { - File tmp = new File(dest,"temporary"); - FileOutputStream fos = new FileOutputStream(tmp); - thingy.reportStringProgress(R.string.multirt_progress_caching); - IOUtils.copy(runtimeInputStream,fos); - fos.close(); - runtimeInputStream.close(); - uncompressTarXZ(tmp,dest,thingy); - tmp.delete(); - } + public static void postPrepare(Context ctx, String name) throws IOException { - File dest = new File(runtimeFolder,"/"+name); + File dest = new File(RUNTIME_FOLDER,"/" + name); if(!dest.exists()) return; - Runtime r = read(name); + Runtime runtime = read(name); String libFolder = "lib"; - if(new File(dest,libFolder+"/"+r.arch).exists()) libFolder = libFolder+"/"+r.arch; - File ftIn = new File(dest, libFolder+ "/libfreetype.so.6"); + if(new File(dest,libFolder + "/" + runtime.arch).exists()) libFolder = libFolder + "/" + runtime.arch; + File ftIn = new File(dest, libFolder + "/libfreetype.so.6"); File ftOut = new File(dest, libFolder + "/libfreetype.so"); if (ftIn.exists() && (!ftOut.exists() || ftIn.length() != ftOut.length())) { ftIn.renameTo(ftOut); } // Refresh libraries - copyDummyNativeLib(ctx,"libawt_xawt.so",dest,libFolder); + copyDummyNativeLib(ctx,"libawt_xawt.so", dest, libFolder); } - private static void copyDummyNativeLib(Context ctx, String name, File dest, String libFolder) throws IOException { - File fileLib = new File(dest, "/"+libFolder + "/" + name); - fileLib.delete(); - FileInputStream is = new FileInputStream(new File(ctx.getApplicationInfo().nativeLibraryDir, name)); - FileOutputStream os = new FileOutputStream(fileLib); - IOUtils.copy(is, os); - is.close(); - os.close(); - } - public static Runtime installRuntimeNamedBinpack(InputStream universalFileInputStream, InputStream platformBinsInputStream, String name, String binpackVersion, ProgressReporterThingy thingy) throws IOException { - File dest = new File(runtimeFolder,"/"+name); + public static Runtime installRuntimeNamedBinpack(InputStream universalFileInputStream, InputStream platformBinsInputStream, String name, String binpackVersion, RuntimeProgressReporter thingy) throws IOException { + File dest = new File(RUNTIME_FOLDER,"/"+name); if(dest.exists()) FileUtils.deleteDirectory(dest); dest.mkdirs(); - __installRuntimeNamed__NoRM(universalFileInputStream,dest,thingy); - __installRuntimeNamed__NoRM(platformBinsInputStream,dest,thingy); - File binpack_verfile = new File(runtimeFolder,"/"+name+"/pojav_version"); + installRuntimeNamedNoRemove(universalFileInputStream,dest,thingy); + installRuntimeNamedNoRemove(platformBinsInputStream,dest,thingy); + File binpack_verfile = new File(RUNTIME_FOLDER,"/"+name+"/pojav_version"); FileOutputStream fos = new FileOutputStream(binpack_verfile); fos.write(binpackVersion.getBytes()); fos.close(); - cache.remove(name); // Force reread + sCache.remove(name); // Force reread return read(name); } + public static String __internal__readBinpackVersion(String name) { - File binpack_verfile = new File(runtimeFolder,"/"+name+"/pojav_version"); + File binpack_verfile = new File(RUNTIME_FOLDER,"/"+name+"/pojav_version"); try { if (binpack_verfile.exists()) { return Tools.read(binpack_verfile.getAbsolutePath()); @@ -162,38 +130,42 @@ public class MultiRTUtils { return null; } } + public static void removeRuntimeNamed(String name) throws IOException { - File dest = new File(runtimeFolder,"/"+name); + File dest = new File(RUNTIME_FOLDER,"/"+name); if(dest.exists()) { FileUtils.deleteDirectory(dest); - cache.remove(name); + sCache.remove(name); } } + public static void setRuntimeNamed(Context ctx, String name) throws IOException { - File dest = new File(runtimeFolder,"/"+name); + File dest = new File(RUNTIME_FOLDER,"/"+name); if((!dest.exists()) || MultiRTUtils.forceReread(name).versionString == null) throw new RuntimeException("Selected runtime is broken!"); Tools.DIR_HOME_JRE = dest.getAbsolutePath(); JREUtils.relocateLibPath(ctx); } + public static Runtime forceReread(String name) { - cache.remove(name); + sCache.remove(name); return read(name); } + public static Runtime read(String name) { - if(cache.containsKey(name)) return cache.get(name); - Runtime retur; - File release = new File(runtimeFolder,"/"+name+"/release"); + if(sCache.containsKey(name)) return sCache.get(name); + Runtime returnRuntime; + File release = new File(RUNTIME_FOLDER,"/"+name+"/release"); if(!release.exists()) { return new Runtime(name); } try { String content = Tools.read(release.getAbsolutePath()); - int _JAVA_VERSION_index = content.indexOf(JAVA_VERSION_str); - int _OS_ARCH_index = content.indexOf(OS_ARCH_str); - if(_JAVA_VERSION_index != -1 && _OS_ARCH_index != -1) { - _JAVA_VERSION_index += JAVA_VERSION_str.length(); - _OS_ARCH_index += OS_ARCH_str.length(); - String javaVersion = content.substring(_JAVA_VERSION_index,content.indexOf('"',_JAVA_VERSION_index)); + int javaVersionIndex = content.indexOf(JAVA_VERSION_STR); + int osArchIndex = content.indexOf(OS_ARCH_STR); + if(javaVersionIndex != -1 && osArchIndex != -1) { + javaVersionIndex += JAVA_VERSION_STR.length(); + osArchIndex += OS_ARCH_STR.length(); + String javaVersion = content.substring(javaVersionIndex,content.indexOf('"', javaVersionIndex)); String[] javaVersionSplit = javaVersion.split("\\."); int javaVersionInt; if (javaVersionSplit[0].equals("1")) { @@ -201,25 +173,46 @@ public class MultiRTUtils { } else { javaVersionInt = Integer.parseInt(javaVersionSplit[0]); } - Runtime r = new Runtime(name); - r.arch = content.substring(_OS_ARCH_index,content.indexOf('"',_OS_ARCH_index)); - r.javaVersion = javaVersionInt; - r.versionString = javaVersion; - retur = r; + Runtime runtime = new Runtime(name); + runtime.arch = content.substring(osArchIndex,content.indexOf('"', osArchIndex)); + runtime.javaVersion = javaVersionInt; + runtime.versionString = javaVersion; + returnRuntime = runtime; }else{ - retur = new Runtime(name); + returnRuntime = new Runtime(name); } }catch(IOException e) { - retur = new Runtime(name); + returnRuntime = new Runtime(name); } - cache.put(name,retur); - return retur; + sCache.put(name, returnRuntime); + return returnRuntime; } - private static void uncompressTarXZ(final File tarFile, final File dest, final ProgressReporterThingy thingy) throws IOException { - dest.mkdirs(); - TarArchiveInputStream tarIn = null; - tarIn = new TarArchiveInputStream( + private static void copyDummyNativeLib(Context ctx, String name, File dest, String libFolder) throws IOException { + File fileLib = new File(dest, "/"+libFolder + "/" + name); + fileLib.delete(); + FileInputStream is = new FileInputStream(new File(ctx.getApplicationInfo().nativeLibraryDir, name)); + FileOutputStream os = new FileOutputStream(fileLib); + IOUtils.copy(is, os); + is.close(); + os.close(); + } + + private static void installRuntimeNamedNoRemove(InputStream runtimeInputStream, File dest, RuntimeProgressReporter progressReporter) throws IOException { + File tmp = new File(dest,"temporary"); + FileOutputStream fos = new FileOutputStream(tmp); + progressReporter.reportStringProgress(R.string.multirt_progress_caching); + IOUtils.copy(runtimeInputStream,fos); + fos.close(); + runtimeInputStream.close(); + uncompressTarXZ(tmp,dest,progressReporter); + tmp.delete(); + } + + private static void uncompressTarXZ(final File tarFile, final File dest, final RuntimeProgressReporter thingy) throws IOException { + dest.mkdirs(); + + TarArchiveInputStream tarIn = new TarArchiveInputStream( new XZCompressorInputStream( new BufferedInputStream( new FileInputStream(tarFile) @@ -251,7 +244,7 @@ public class MultiRTUtils { // Libcore one support all Android versions Os.symlink(tarEntry.getName(), tarEntry.getLinkName()); } catch (Throwable e) { - e.printStackTrace(); + Log.e("MultiRT", e.toString()); } } else if (tarEntry.isDirectory()) { diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java index 54bb5a4f8..cec96f6a0 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java @@ -23,115 +23,126 @@ import java.io.IOException; import java.util.List; public class RTRecyclerViewAdapter extends RecyclerView.Adapter { - MultiRTConfigDialog dialog; + + MultiRTConfigDialog mConfigDialog; public RTRecyclerViewAdapter(MultiRTConfigDialog dialog) { - this.dialog = dialog; + this.mConfigDialog = dialog; } + @NonNull @Override public RTViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View recyclableView = LayoutInflater.from(parent.getContext()).inflate(R.layout.multirt_recyclable_view,parent,false); + View recyclableView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_multirt_runtime,parent,false); return new RTViewHolder(recyclableView); } @Override public void onBindViewHolder(@NonNull RTViewHolder holder, int position) { - final List runtimes = MultiRTUtils.getRuntimes(); + final List runtimes = MultiRTUtils.getRuntimes(); holder.bindRuntime(runtimes.get(position),position); } - public boolean isDefaultRuntime(MultiRTUtils.Runtime rt) { - return LauncherPreferences.PREF_DEFAULT_RUNTIME.equals(rt.name); - } - public void setDefault(MultiRTUtils.Runtime rt){ - LauncherPreferences.PREF_DEFAULT_RUNTIME = rt.name; - LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply(); - RTRecyclerViewAdapter.this.notifyDataSetChanged(); - } + @Override public int getItemCount() { return MultiRTUtils.getRuntimes().size(); } + + public boolean isDefaultRuntime(Runtime rt) { + return LauncherPreferences.PREF_DEFAULT_RUNTIME.equals(rt.name); + } + + public void setDefault(Runtime rt){ + LauncherPreferences.PREF_DEFAULT_RUNTIME = rt.name; + LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply(); + RTRecyclerViewAdapter.this.notifyDataSetChanged(); + } + + public class RTViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ - final TextView javaVersionView; - final TextView fullJavaVersionView; - final ColorStateList defaultColors; - final Button setDefaultButton; - final Context ctx; - MultiRTUtils.Runtime currentRuntime; - int currentPosition; + final TextView mJavaVersionTextView; + final TextView mFullJavaVersionTextView; + final ColorStateList mDefaultColors; + final Button mSetDefaultButton; + final Context mContext; + Runtime mCurrentRuntime; + int mCurrentPosition; + public RTViewHolder(View itemView) { super(itemView); - javaVersionView = itemView.findViewById(R.id.multirt_view_java_version); - fullJavaVersionView = itemView.findViewById(R.id.multirt_view_java_version_full); + mJavaVersionTextView = itemView.findViewById(R.id.multirt_view_java_version); + mFullJavaVersionTextView = itemView.findViewById(R.id.multirt_view_java_version_full); + mSetDefaultButton = itemView.findViewById(R.id.multirt_view_setdefaultbtn); + mSetDefaultButton.setOnClickListener(this); + mDefaultColors = mFullJavaVersionTextView.getTextColors(); + mContext = itemView.getContext(); itemView.findViewById(R.id.multirt_view_removebtn).setOnClickListener(this); - setDefaultButton = itemView.findViewById(R.id.multirt_view_setdefaultbtn); - setDefaultButton.setOnClickListener(this); - defaultColors = fullJavaVersionView.getTextColors(); - ctx = itemView.getContext(); - } - public void bindRuntime(MultiRTUtils.Runtime rt, int pos) { - currentRuntime = rt; - currentPosition = pos; - if(rt.versionString != null && Tools.DEVICE_ARCHITECTURE == Architecture.archAsInt(rt.arch)) { - javaVersionView.setText(ctx.getString(R.string.multirt_java_ver, rt.name, rt.javaVersion)); - fullJavaVersionView.setText(rt.versionString); - fullJavaVersionView.setTextColor(defaultColors); - setDefaultButton.setVisibility(View.VISIBLE); - boolean default_ = isDefaultRuntime(rt); - setDefaultButton.setEnabled(!default_); - setDefaultButton.setText(default_?R.string.multirt_config_setdefault_already:R.string.multirt_config_setdefault); - }else{ - if(rt.versionString == null){ - fullJavaVersionView.setText(R.string.multirt_runtime_corrupt); - }else{ - fullJavaVersionView.setText(ctx.getString(R.string.multirt_runtime_incompatiblearch, rt.arch)); - } - javaVersionView.setText(rt.name); - fullJavaVersionView.setTextColor(Color.RED); - setDefaultButton.setVisibility(View.GONE); - } } @Override - public void onClick(View v) { - if(v.getId() == R.id.multirt_view_removebtn) { - if (currentRuntime != null) { - if(MultiRTUtils.getRuntimes().size() < 2 && setDefaultButton.isShown()) { - AlertDialog.Builder bldr = new AlertDialog.Builder(ctx); - bldr.setTitle(R.string.global_error); - bldr.setMessage(R.string.multirt_config_removeerror_last); - bldr.setPositiveButton(android.R.string.ok,(adapter, which)->adapter.dismiss()); - bldr.show(); - return; - } + public void onClick(View view) { + if(view.getId() == R.id.multirt_view_removebtn) { + if (mCurrentRuntime == null) return; - final ProgressDialog barrier = new ProgressDialog(ctx); - barrier.setMessage(ctx.getString(R.string.global_waiting)); - barrier.setProgressStyle(ProgressDialog.STYLE_SPINNER); - barrier.setCancelable(false); - barrier.show(); - Thread t = new Thread(() -> { - try { - MultiRTUtils.removeRuntimeNamed(currentRuntime.name); - } catch (IOException e) { - Tools.showError(itemView.getContext(), e); - } - v.post(() -> { - if(isDefaultRuntime(currentRuntime)) setDefault(MultiRTUtils.getRuntimes().get(0)); - barrier.dismiss(); - RTRecyclerViewAdapter.this.notifyDataSetChanged(); - dialog.dialog.show(); - }); - }); - t.start(); + if(MultiRTUtils.getRuntimes().size() < 2 && mSetDefaultButton.isShown()) { + AlertDialog.Builder bldr = new AlertDialog.Builder(mContext); + bldr.setTitle(R.string.global_error); + bldr.setMessage(R.string.multirt_config_removeerror_last); + bldr.setPositiveButton(android.R.string.ok,(adapter, which)->adapter.dismiss()); + bldr.show(); + return; } - }else if(v.getId() == R.id.multirt_view_setdefaultbtn) { - if(currentRuntime != null) { - setDefault(currentRuntime); + + final ProgressDialog barrier = new ProgressDialog(mContext); + barrier.setMessage(mContext.getString(R.string.global_waiting)); + barrier.setProgressStyle(ProgressDialog.STYLE_SPINNER); + barrier.setCancelable(false); + barrier.show(); + Thread t = new Thread(() -> { + try { + MultiRTUtils.removeRuntimeNamed(mCurrentRuntime.name); + } catch (IOException e) { + Tools.showError(itemView.getContext(), e); + } + view.post(() -> { + if(isDefaultRuntime(mCurrentRuntime)) setDefault(MultiRTUtils.getRuntimes().get(0)); + barrier.dismiss(); + RTRecyclerViewAdapter.this.notifyDataSetChanged(); + mConfigDialog.mDialog.show(); + }); + }); + t.start(); + + }else if(view.getId() == R.id.multirt_view_setdefaultbtn) { + if(mCurrentRuntime != null) { + setDefault(mCurrentRuntime); RTRecyclerViewAdapter.this.notifyDataSetChanged(); } } } + public void bindRuntime(Runtime runtime, int pos) { + mCurrentRuntime = runtime; + mCurrentPosition = pos; + if(runtime.versionString != null && Tools.DEVICE_ARCHITECTURE == Architecture.archAsInt(runtime.arch)) { + mJavaVersionTextView.setText(mContext.getString(R.string.multirt_java_ver, runtime.name, runtime.javaVersion)); + mFullJavaVersionTextView.setText(runtime.versionString); + mFullJavaVersionTextView.setTextColor(mDefaultColors); + mSetDefaultButton.setVisibility(View.VISIBLE); + boolean defaultRuntime = isDefaultRuntime(runtime); + mSetDefaultButton.setEnabled(!defaultRuntime); + mSetDefaultButton.setText(defaultRuntime ? R.string.multirt_config_setdefault_already:R.string.multirt_config_setdefault); + return; + } + + // Problematic runtime moment + if(runtime.versionString == null){ + mFullJavaVersionTextView.setText(R.string.multirt_runtime_corrupt); + }else{ + mFullJavaVersionTextView.setText(mContext.getString(R.string.multirt_runtime_incompatiblearch, runtime.arch)); + } + mJavaVersionTextView.setText(runtime.name); + mFullJavaVersionTextView.setTextColor(Color.RED); + mSetDefaultButton.setVisibility(View.GONE); + } } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTSpinnerAdapter.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTSpinnerAdapter.java index 4a499c371..776453a73 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTSpinnerAdapter.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTSpinnerAdapter.java @@ -16,39 +16,39 @@ import net.kdt.pojavlaunch.R; import java.util.List; public class RTSpinnerAdapter implements SpinnerAdapter { - final Context ctx; - List runtimes; - public RTSpinnerAdapter(@NonNull Context context, List runtimes) { - this.runtimes = runtimes; - MultiRTUtils.Runtime runtime = new MultiRTUtils.Runtime(""); + final Context mContext; + List mRuntimes; + public RTSpinnerAdapter(@NonNull Context context, List runtimes) { + mRuntimes = runtimes; + Runtime runtime = new Runtime(""); runtime.versionString = ""; - this.runtimes.add(runtime); - ctx = context; + mRuntimes.add(runtime); + mContext = context; } @Override public void registerDataSetObserver(DataSetObserver observer) { - + //STUB } @Override public void unregisterDataSetObserver(DataSetObserver observer) { - + //STUB } @Override public int getCount() { - return runtimes.size(); + return mRuntimes.size(); } @Override public Object getItem(int position) { - return runtimes.get(position); + return mRuntimes.get(position); } @Override public long getItemId(int position) { - return runtimes.get(position).name.hashCode(); + return mRuntimes.get(position).name.hashCode(); } @Override @@ -59,25 +59,25 @@ public class RTSpinnerAdapter implements SpinnerAdapter { @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { - View v = convertView!=null? + View view = convertView != null? convertView: - LayoutInflater.from(ctx).inflate(R.layout.multirt_recyclable_view,parent,false); + LayoutInflater.from(mContext).inflate(R.layout.item_multirt_runtime,parent,false); - MultiRTUtils.Runtime rt = runtimes.get(position); + Runtime runtime = mRuntimes.get(position); - final TextView javaVersionView = v.findViewById(R.id.multirt_view_java_version); - final TextView fullJavaVersionView = v.findViewById(R.id.multirt_view_java_version_full); - v.findViewById(R.id.multirt_view_removebtn).setVisibility(View.GONE); - v.findViewById(R.id.multirt_view_setdefaultbtn).setVisibility(View.GONE); + final TextView javaVersionView = view.findViewById(R.id.multirt_view_java_version); + final TextView fullJavaVersionView = view.findViewById(R.id.multirt_view_java_version_full); + view.findViewById(R.id.multirt_view_removebtn).setVisibility(View.GONE); + view.findViewById(R.id.multirt_view_setdefaultbtn).setVisibility(View.GONE); - if(rt.versionString != null) { - javaVersionView.setText(ctx.getString(R.string.multirt_java_ver, rt.name, rt.javaVersion)); - fullJavaVersionView.setText(rt.versionString); + if(runtime.versionString != null) { + javaVersionView.setText(mContext.getString(R.string.multirt_java_ver, runtime.name, runtime.javaVersion)); + fullJavaVersionView.setText(runtime.versionString); }else{ - javaVersionView.setText(rt.name); + javaVersionView.setText(runtime.name); fullJavaVersionView.setText(R.string.multirt_runtime_corrupt); } - return v; + return view; } @Override @@ -92,7 +92,7 @@ public class RTSpinnerAdapter implements SpinnerAdapter { @Override public boolean isEmpty() { - return runtimes.isEmpty(); + return mRuntimes.isEmpty(); } @Override diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/Runtime.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/Runtime.java new file mode 100644 index 000000000..9c4d7897e --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/Runtime.java @@ -0,0 +1,26 @@ +package net.kdt.pojavlaunch.multirt; + +import java.util.Objects; + +public class Runtime { + public Runtime(String name) { + this.name = name; + } + + public String name; + public String versionString; + public String arch; + public int javaVersion; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Runtime runtime = (Runtime) o; + return name.equals(runtime.name); + } + @Override + public int hashCode() { + return Objects.hash(name); + } +} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/ControlOffsetPreference.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/ControlOffsetPreference.java index 3d07fb242..a378017a5 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/ControlOffsetPreference.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/ControlOffsetPreference.java @@ -20,9 +20,7 @@ import net.kdt.pojavlaunch.R; /** Custom preference class displaying a dialog */ public class ControlOffsetPreference extends Preference { - private AlertDialog preferenceDialog; - - + private AlertDialog mPreferenceDialog; public ControlOffsetPreference(Context context, AttributeSet attrs) { super(context, attrs); @@ -34,43 +32,19 @@ public class ControlOffsetPreference extends Preference { init(); } - - private void init(){ - // Setup visual values - if(getTitle() == null){ - setTitle(R.string.preference_control_offset_title); - setSummary(R.string.preference_control_offset_description); - } - if(getIcon() == null){ - setIcon(android.R.drawable.radiobutton_off_background); - } - - // Prepare Alert dialog - AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext()); - dialogBuilder.setView(R.layout.control_offset_preference_dialog); - dialogBuilder.setTitle(getContext().getString(R.string.control_offset_title)); - - dialogBuilder.setPositiveButton(android.R.string.ok, null); - dialogBuilder.setNegativeButton(android.R.string.cancel, null); - - preferenceDialog = dialogBuilder.create(); - - - } - @Override protected void onClick() { - preferenceDialog.show(); + mPreferenceDialog.show(); - SeekBar topOffsetSeekbar = preferenceDialog.findViewById(R.id.control_offset_top_seekbar); - SeekBar rightOffsetSeekbar = preferenceDialog.findViewById(R.id.control_offset_right_seekbar); - SeekBar bottomOffsetSeekbar = preferenceDialog.findViewById(R.id.control_offset_bottom_seekbar); - SeekBar leftOffsetSeekbar = preferenceDialog.findViewById(R.id.control_offset_left_seekbar); + SeekBar topOffsetSeekbar = mPreferenceDialog.findViewById(R.id.control_offset_top_seekbar); + SeekBar rightOffsetSeekbar = mPreferenceDialog.findViewById(R.id.control_offset_right_seekbar); + SeekBar bottomOffsetSeekbar = mPreferenceDialog.findViewById(R.id.control_offset_bottom_seekbar); + SeekBar leftOffsetSeekbar = mPreferenceDialog.findViewById(R.id.control_offset_left_seekbar); - TextView topOffsetTextView = preferenceDialog.findViewById(R.id.control_offset_top_textview); - TextView rightOffsetTextView = preferenceDialog.findViewById(R.id.control_offset_right_textview); - TextView bottomOffsetTextView = preferenceDialog.findViewById(R.id.control_offset_bottom_textview); - TextView leftOffsetTextView = preferenceDialog.findViewById(R.id.control_offset_left_textview); + TextView topOffsetTextView = mPreferenceDialog.findViewById(R.id.control_offset_top_textview); + TextView rightOffsetTextView = mPreferenceDialog.findViewById(R.id.control_offset_right_textview); + TextView bottomOffsetTextView = mPreferenceDialog.findViewById(R.id.control_offset_bottom_textview); + TextView leftOffsetTextView = mPreferenceDialog.findViewById(R.id.control_offset_left_textview); SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { @Override @@ -118,15 +92,36 @@ public class ControlOffsetPreference extends Preference { seekBarChangeListener.onProgressChanged(leftOffsetSeekbar, PREF_CONTROL_LEFT_OFFSET, false); // Custom writing to preferences - preferenceDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(view -> { + mPreferenceDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(view -> { DEFAULT_PREF.edit().putInt("controlTopOffset", topOffsetSeekbar.getProgress()).apply(); DEFAULT_PREF.edit().putInt("controlRightOffset", rightOffsetSeekbar.getProgress()).apply(); DEFAULT_PREF.edit().putInt("controlBottomOffset", bottomOffsetSeekbar.getProgress()).apply(); DEFAULT_PREF.edit().putInt("controlLeftOffset", leftOffsetSeekbar.getProgress()).apply(); - preferenceDialog.dismiss(); + mPreferenceDialog.dismiss(); }); } + private void init(){ + // Setup visual values + if(getTitle() == null){ + setTitle(R.string.preference_control_offset_title); + setSummary(R.string.preference_control_offset_description); + } + if(getIcon() == null){ + setIcon(android.R.drawable.radiobutton_off_background); + } + + // Prepare Alert dialog + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext()); + dialogBuilder.setView(R.layout.dialog_control_offset_preference); + dialogBuilder.setTitle(getContext().getString(R.string.control_offset_title)); + + dialogBuilder.setPositiveButton(android.R.string.ok, null); + dialogBuilder.setNegativeButton(android.R.string.cancel, null); + + mPreferenceDialog = dialogBuilder.create(); + } + } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/CustomSeekBarPreference.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/CustomSeekBarPreference.java index a6425b1a6..925289dd2 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/CustomSeekBarPreference.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/CustomSeekBarPreference.java @@ -16,11 +16,11 @@ import net.kdt.pojavlaunch.R; public class CustomSeekBarPreference extends SeekBarPreference { /** The suffix displayed */ - private String suffix = ""; + private String mSuffix = ""; /** Custom minimum value to provide the same behavior as the usual setMin */ private int mMin; /** The textview associated by default to the preference */ - private TextView textView; + private TextView mTextView; public CustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { @@ -37,7 +37,6 @@ public class CustomSeekBarPreference extends SeekBarPreference { public CustomSeekBarPreference(Context context, AttributeSet attrs) { this(context, attrs, R.attr.seekBarPreferenceStyle); - } public CustomSeekBarPreference(Context context) { @@ -58,8 +57,8 @@ public class CustomSeekBarPreference extends SeekBarPreference { TextView titleTextView = (TextView) view.findViewById(android.R.id.title); titleTextView.setTextColor(Color.WHITE); - textView = (TextView) view.findViewById(R.id.seekbar_value); - textView.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START); + mTextView = (TextView) view.findViewById(R.id.seekbar_value); + mTextView.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START); SeekBar seekBar = (SeekBar) view.findViewById(R.id.seekbar); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @@ -71,7 +70,7 @@ public class CustomSeekBarPreference extends SeekBarPreference { progress = progress * getSeekBarIncrement(); progress -= mMin; - textView.setText(String.valueOf(progress + mMin)); + mTextView.setText(String.valueOf(progress + mMin)); updateTextViewWithSuffix(); } @@ -94,20 +93,12 @@ public class CustomSeekBarPreference extends SeekBarPreference { updateTextViewWithSuffix(); } - - private void updateTextViewWithSuffix(){ - if(!textView.getText().toString().endsWith(suffix)){ - textView.setText(String.format("%s%s", textView.getText(), suffix)); - } - - } - /** * Set a suffix to be appended on the TextView associated to the value * @param suffix The suffix to append as a String */ public void setSuffix(String suffix) { - this.suffix = suffix; + this.mSuffix = suffix; } /** @@ -119,4 +110,11 @@ public class CustomSeekBarPreference extends SeekBarPreference { setMin(min); setMax(max); } + + + private void updateTextViewWithSuffix(){ + if(!mTextView.getText().toString().endsWith(mSuffix)){ + mTextView.setText(String.format("%s%s", mTextView.getText(), mSuffix)); + } + } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/PerVersionConfigDialog.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/PerVersionConfigDialog.java index 78db13c93..2b5f000e9 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/PerVersionConfigDialog.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/PerVersionConfigDialog.java @@ -13,108 +13,112 @@ import androidx.appcompat.app.AlertDialog; import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.multirt.RTSpinnerAdapter; -import net.kdt.pojavlaunch.tasks.RefreshVersionListTask; +import net.kdt.pojavlaunch.multirt.Runtime; import net.kdt.pojavlaunch.value.PerVersionConfig; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.List; public class PerVersionConfigDialog{ - final Context ctx; - final AlertDialog dialog; - final View v; - List runtimes; - final Spinner javaVMSpinner; - final Spinner rendererSpinner; - final EditText customDirText; - final EditText jvmArgsEditText; - final List renderNames; - String selectedGameVersion = null; - public PerVersionConfigDialog(Context _ctx) { - ctx = _ctx; - v = LayoutInflater.from(ctx).inflate(R.layout.pvc_popup,null); - javaVMSpinner = v.findViewById(R.id.pvc_javaVm); - rendererSpinner = v.findViewById(R.id.pvc_renderer); - { - List renderList = new ArrayList<>(); - Collections.addAll(renderList, ctx.getResources().getStringArray(R.array.renderer)); - renderList.add("Default"); - renderNames = Arrays.asList(ctx.getResources().getStringArray(R.array.renderer_values)); - rendererSpinner.setAdapter(new ArrayAdapter<>(ctx, android.R.layout.simple_spinner_dropdown_item,renderList)); - } - customDirText = v.findViewById(R.id.pvc_customDir); - jvmArgsEditText = v.findViewById(R.id.pvc_jvmArgs); - AlertDialog.Builder builder = new AlertDialog.Builder(ctx); - builder.setView(v); + final Context mContext; + final AlertDialog mDialog; + final View mRootView; + List mRuntimes; + final Spinner mJvmSpinner; + final Spinner mRendererSpinner; + final EditText mCustomDirEditText; + final EditText mJvmArgsEditText; + final List mRendererNames; + String mSelectedGameVersion = null; + + public PerVersionConfigDialog(Context ctx) { + mContext = ctx; + mRootView = LayoutInflater.from(mContext).inflate(R.layout.dialog_per_version_control,null); + mJvmSpinner = mRootView.findViewById(R.id.pvc_javaVm); + mRendererSpinner = mRootView.findViewById(R.id.pvc_renderer); + + ArrayList renderList = new ArrayList<>(5); + Collections.addAll(renderList, mContext.getResources().getStringArray(R.array.renderer)); + renderList.add("Default"); + mRendererNames = Arrays.asList(mContext.getResources().getStringArray(R.array.renderer_values)); + mRendererSpinner.setAdapter(new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_dropdown_item, renderList)); + + mCustomDirEditText = mRootView.findViewById(R.id.pvc_customDir); + mJvmArgsEditText = mRootView.findViewById(R.id.pvc_jvmArgs); + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + builder.setView(mRootView); builder.setTitle(R.string.pvc_title); - builder.setNegativeButton(android.R.string.cancel,(dialogInterface,i)->dialogInterface.dismiss()); - builder.setPositiveButton(android.R.string.ok,this::save); - dialog = builder.create(); + builder.setNegativeButton(android.R.string.cancel, null); + builder.setPositiveButton(android.R.string.ok, this::save); + mDialog = builder.create(); } + public void refreshRuntimes() { - if(runtimes!=null)runtimes.clear(); - runtimes = MultiRTUtils.getRuntimes(); - //runtimes.add(new MultiRTUtils.Runtime("")); + if(mRuntimes !=null) mRuntimes.clear(); + mRuntimes = MultiRTUtils.getRuntimes(); + //runtimes.add(new Runtime("")); } - private void save(DialogInterface i, int which) { - if(selectedGameVersion == null) { - i.dismiss(); + + private void save(DialogInterface dialogInterface, int which) { + if(mSelectedGameVersion == null) { + dialogInterface.dismiss(); return; } - PerVersionConfig.VersionConfig conf1 = PerVersionConfig.configMap.get(selectedGameVersion); - if(conf1==null){ - conf1=new PerVersionConfig.VersionConfig(); + + PerVersionConfig.VersionConfig versionConfig = PerVersionConfig.configMap.get(mSelectedGameVersion); + if(versionConfig == null){ + versionConfig = new PerVersionConfig.VersionConfig(); } - conf1.jvmArgs=jvmArgsEditText.getText().toString(); - conf1.gamePath=customDirText.getText().toString(); + versionConfig.jvmArgs= mJvmArgsEditText.getText().toString(); + versionConfig.gamePath= mCustomDirEditText.getText().toString(); - if(rendererSpinner.getSelectedItemPosition() == renderNames.size()) conf1.renderer = null; - else conf1.renderer = renderNames.get(rendererSpinner.getSelectedItemPosition()); + if(mRendererSpinner.getSelectedItemPosition() == mRendererNames.size()) versionConfig.renderer = null; + else versionConfig.renderer = mRendererNames.get(mRendererSpinner.getSelectedItemPosition()); - String runtime=((MultiRTUtils.Runtime)javaVMSpinner.getSelectedItem()).name;; - if(!runtime.equals(""))conf1.selectedRuntime=runtime; - else conf1.selectedRuntime=null; + String runtime=((Runtime) mJvmSpinner.getSelectedItem()).name;; + if(!runtime.equals(""))versionConfig.selectedRuntime=runtime; + else versionConfig.selectedRuntime = null; - PerVersionConfig.configMap.put(selectedGameVersion,conf1); + PerVersionConfig.configMap.put(mSelectedGameVersion, versionConfig); try{ PerVersionConfig.update(); }catch(IOException e){ e.printStackTrace(); } } + public boolean openConfig(String selectedVersion) { - selectedGameVersion = selectedVersion; + mSelectedGameVersion = selectedVersion; try{ PerVersionConfig.update(); }catch(IOException e){ e.printStackTrace(); } - PerVersionConfig.VersionConfig conf=PerVersionConfig.configMap.get(selectedGameVersion); + PerVersionConfig.VersionConfig versionConfig = PerVersionConfig.configMap.get(mSelectedGameVersion); refreshRuntimes(); - javaVMSpinner.setAdapter(new RTSpinnerAdapter(ctx,runtimes)); - { - int jvm_index = runtimes.indexOf(new MultiRTUtils.Runtime("")); - int rnd_index = rendererSpinner.getAdapter().getCount()-1; - if (conf != null) { - customDirText.setText(conf.gamePath); - jvmArgsEditText.setText(conf.jvmArgs); - if (conf.selectedRuntime != null) { - int nindex = runtimes.indexOf(new MultiRTUtils.Runtime(conf.selectedRuntime)); - if (nindex != -1) jvm_index = nindex; - } - if(conf.renderer != null) { - int nindex = renderNames.indexOf(conf.renderer); - if (nindex != -1) rnd_index = nindex; - } + mJvmSpinner.setAdapter(new RTSpinnerAdapter(mContext, mRuntimes)); + + int jvmIndex = mRuntimes.indexOf(new Runtime("")); + int rendererIndex = mRendererSpinner.getAdapter().getCount()-1; + if (versionConfig != null) { + mCustomDirEditText.setText(versionConfig.gamePath); + mJvmArgsEditText.setText(versionConfig.jvmArgs); + if (versionConfig.selectedRuntime != null) { + int nIndex = mRuntimes.indexOf(new Runtime(versionConfig.selectedRuntime)); + if (nIndex != -1) jvmIndex = nIndex; + } + if(versionConfig.renderer != null) { + int nIndex = mRendererNames.indexOf(versionConfig.renderer); + if (nIndex != -1) rendererIndex = nIndex; } - javaVMSpinner.setSelection(jvm_index); - rendererSpinner.setSelection(rnd_index); } - dialog.show(); + mJvmSpinner.setSelection(jvmIndex); + mRendererSpinner.setSelection(rendererIndex); + + mDialog.show(); return true; - } + } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/RuntimeManagerPreference.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/RuntimeManagerPreference.java index 24ff16977..90d459726 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/RuntimeManagerPreference.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/RuntimeManagerPreference.java @@ -6,7 +6,6 @@ import android.util.AttributeSet; import androidx.preference.Preference; import net.kdt.pojavlaunch.BaseLauncherActivity; -import net.kdt.pojavlaunch.multirt.MultiRTConfigDialog; public class RuntimeManagerPreference extends Preference{ public RuntimeManagerPreference(Context ctx) { @@ -17,9 +16,10 @@ public class RuntimeManagerPreference extends Preference{ super(ctx, attrs); setPersistent(false); } + @Override protected void onClick() { super.onClick(); - ((BaseLauncherActivity)this.getContext()).mRuntimeConfigDialog.dialog.show(); + ((BaseLauncherActivity)this.getContext()).mRuntimeConfigDialog.mDialog.show(); } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/scoped/GameFolderProvider.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/scoped/GameFolderProvider.java index cdf997062..c8a92ba1f 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/scoped/GameFolderProvider.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/scoped/GameFolderProvider.java @@ -23,7 +23,7 @@ import java.util.Collections; import java.util.LinkedList; public class GameFolderProvider extends DocumentsProvider { - static File baseDir = new File(Tools.DIR_GAME_HOME); + static File sBaseDir = new File(Tools.DIR_GAME_HOME); private static final String[] DEFAULT_ROOT_PROJECTION = new String[]{ Root.COLUMN_ROOT_ID, Root.COLUMN_MIME_TYPES, @@ -47,13 +47,13 @@ public class GameFolderProvider extends DocumentsProvider { public Cursor queryRoots(String[] projection) throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION); final MatrixCursor.RowBuilder row = result.newRow(); - row.add(Root.COLUMN_ROOT_ID, baseDir.getAbsolutePath()); - row.add(Root.COLUMN_DOCUMENT_ID, baseDir.getAbsolutePath()); + row.add(Root.COLUMN_ROOT_ID, sBaseDir.getAbsolutePath()); + row.add(Root.COLUMN_DOCUMENT_ID, sBaseDir.getAbsolutePath()); row.add(Root.COLUMN_SUMMARY, null); row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_RECENTS | Root.FLAG_SUPPORTS_SEARCH); row.add(Root.COLUMN_TITLE, getContext().getString(R.string.app_name)); row.add(Root.COLUMN_MIME_TYPES, "*/*"); - row.add(Root.COLUMN_AVAILABLE_BYTES, baseDir.getFreeSpace()); + row.add(Root.COLUMN_AVAILABLE_BYTES, sBaseDir.getFreeSpace()); row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher); return result; } @@ -112,7 +112,7 @@ public class GameFolderProvider extends DocumentsProvider { final File file = pending.removeFirst(); boolean isInsideGameDir; try { - isInsideGameDir = file.getCanonicalPath().startsWith(baseDir.getCanonicalPath()); + isInsideGameDir = file.getCanonicalPath().startsWith(sBaseDir.getCanonicalPath()); } catch (IOException e) { isInsideGameDir = true; } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java index 60aeb66dc..82e4e96ad 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java @@ -2,16 +2,15 @@ package net.kdt.pojavlaunch.tasks; import android.app.*; import android.content.*; -import android.content.res.AssetManager; -import android.graphics.*; import android.os.*; import android.util.*; -import com.google.gson.*; + import java.io.*; import java.util.*; import java.util.concurrent.*; import net.kdt.pojavlaunch.*; import net.kdt.pojavlaunch.multirt.MultiRTUtils; +import net.kdt.pojavlaunch.multirt.Runtime; import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.utils.*; import net.kdt.pojavlaunch.value.*; @@ -280,7 +279,7 @@ public class MinecraftDownloaderTask extends AsyncTask{ try { - if (!assets.map_to_resources) { + if (!assets.mapToResources) { downloadAsset(asset, objectsDir, downloadedSize); } else { downloadAssetMapped(asset, assetKey, outputDir, downloadedSize); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java index d5f9e0c2c..21d2e69d0 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java @@ -1,7 +1,6 @@ package net.kdt.pojavlaunch.utils; import static net.kdt.pojavlaunch.Architecture.ARCH_X86; -import static net.kdt.pojavlaunch.Architecture.archAsString; import static net.kdt.pojavlaunch.Architecture.is64BitsDevice; import static net.kdt.pojavlaunch.Tools.LOCAL_RENDERER; import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_GLES_SHRINK_HACK; @@ -15,7 +14,6 @@ import android.system.*; import android.util.*; import android.widget.Toast; -import com.kdt.LoggerView; import com.oracle.dalvik.*; import java.io.*; import java.util.*; @@ -32,21 +30,20 @@ public class JREUtils { private JREUtils() {} public static String LD_LIBRARY_PATH; - private static String nativeLibDir; public static Map jreReleaseList; + public static String jvmLibraryPath; + private static String sNativeLibDir; public static String findInLdLibPath(String libName) { if(Os.getenv("LD_LIBRARY_PATH")==null) { try { if (LD_LIBRARY_PATH != null) { Os.setenv("LD_LIBRARY_PATH", LD_LIBRARY_PATH, true); - }else{ - return libName; } }catch (ErrnoException e) { e.printStackTrace(); - return libName; } + return libName; } for (String libPath : Os.getenv("LD_LIBRARY_PATH").split(":")) { File f = new File(libPath, libName); @@ -56,18 +53,22 @@ public class JREUtils { } return libName; } + public static ArrayList locateLibs(File path) { - ArrayList ret = new ArrayList<>(); + ArrayList returnValue = new ArrayList<>(); File[] list = path.listFiles(); - if(list != null) {for(File f : list) { - if(f.isFile() && f.getName().endsWith(".so")) { - ret.add(f); - }else if(f.isDirectory()) { - ret.addAll(locateLibs(f)); + if(list != null) { + for(File f : list) { + if(f.isFile() && f.getName().endsWith(".so")) { + returnValue.add(f); + }else if(f.isDirectory()) { + returnValue.addAll(locateLibs(f)); + } } - }} - return ret; + } + return returnValue; } + public static void initJavaRuntime() { dlopen(findInLdLibPath("libjli.so")); if(!dlopen("libjvm.so")){ @@ -86,13 +87,13 @@ public class JREUtils { for(File f : locateLibs(new File(Tools.DIR_HOME_JRE + "/" + Tools.DIRNAME_HOME_JRE))) { dlopen(f.getAbsolutePath()); } - dlopen(nativeLibDir + "/libopenal.so"); - + dlopen(sNativeLibDir + "/libopenal.so"); } public static Map readJREReleaseProperties() throws IOException { return readJREReleaseProperties(Tools.DIR_HOME_JRE); } + public static Map readJREReleaseProperties(String name) throws IOException { Map jreReleaseMap = new ArrayMap<>(); if (!name.contains("/")) { @@ -109,11 +110,11 @@ public class JREUtils { jreReleaseReader.close(); return jreReleaseMap; } - public static String jvmLibraryPath; - public static void redirectAndPrintJRELog(final Context ctx) { + + public static void redirectAndPrintJRELog() { Log.v("jrelog","Log starts here"); JREUtils.logToLogger(Logger.getInstance()); - Thread t = new Thread(new Runnable(){ + new Thread(new Runnable(){ int failTime = 0; ProcessBuilder logcatPb; @Override @@ -128,16 +129,6 @@ public class JREUtils { Log.i("jrelog-logcat","Starting logcat"); java.lang.Process p = logcatPb.start(); - // idk which better, both have a bug that printf(\n) in a single line - /* - BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - act.appendlnToLog(line); - } - reader.close(); - */ - byte[] buf = new byte[1024]; int len; while ((len = p.getInputStream().read(buf)) != -1) { @@ -161,8 +152,7 @@ public class JREUtils { Logger.getInstance().appendToLog("Exception on logging thread:\n" + Log.getStackTraceString(e)); } } - }); - t.start(); + }).start(); Log.i("jrelog-logcat","Logcat thread started"); } @@ -172,7 +162,7 @@ public class JREUtils { JRE_ARCHITECTURE = "i386/i486/i586"; } - nativeLibDir = ctx.getApplicationInfo().nativeLibraryDir; + sNativeLibDir = ctx.getApplicationInfo().nativeLibraryDir; for (String arch : JRE_ARCHITECTURE.split("/")) { File f = new File(Tools.DIR_HOME_JRE, "lib/" + arch); @@ -191,7 +181,7 @@ public class JREUtils { "/system/" + libName + ":" + "/vendor/" + libName + ":" + "/vendor/" + libName + "/hw:" + - nativeLibDir + sNativeLibDir ); LD_LIBRARY_PATH = ldLibraryPath.toString(); } @@ -461,7 +451,7 @@ public class JREUtils { Log.e("RENDER_LIBRARY","Failed to load renderer " + renderLibrary + ". Falling back to GL4ES 1.1.4"); LOCAL_RENDERER = "opengles2"; renderLibrary = "libgl4es_114.so"; - dlopen(nativeLibDir + "/libgl4es_114.so"); + dlopen(sNativeLibDir + "/libgl4es_114.so"); } return renderLibrary; } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/MCOptionUtils.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/MCOptionUtils.java index 353f5343f..51114b68d 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/MCOptionUtils.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/MCOptionUtils.java @@ -20,22 +20,21 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; -public class MCOptionUtils -{ - private static final HashMap parameterMap = new HashMap<>(); - private static final ArrayList> optionListeners = new ArrayList<>(); - private static FileObserver fileObserver; +public class MCOptionUtils { + private static final HashMap sParameterMap = new HashMap<>(); + private static final ArrayList> sOptionListeners = new ArrayList<>(); + private static FileObserver sFileObserver; public interface MCOptionListener { /** Called when an option is changed. Don't know which one though */ void onOptionChanged(); } public static void load() { - if(fileObserver == null){ + if(sFileObserver == null){ setupFileObserver(); } - parameterMap.clear(); + sParameterMap.clear(); try { BufferedReader reader = new BufferedReader(new FileReader(Tools.DIR_GAME_NEW + "/options.txt")); @@ -46,7 +45,7 @@ public class MCOptionUtils Log.w(Tools.APP_NAME, "No colon on line \""+line+"\", skipping"); continue; } - parameterMap.put(line.substring(0,firstColonIndex), line.substring(firstColonIndex+1)); + sParameterMap.put(line.substring(0,firstColonIndex), line.substring(firstColonIndex+1)); } reader.close(); } catch (IOException e) { @@ -55,16 +54,16 @@ public class MCOptionUtils } public static void set(String key, String value) { - parameterMap.put(key,value); + sParameterMap.put(key,value); } /** Set an array of String, instead of a simple value. Not supported on all options */ public static void set(String key, List values){ - parameterMap.put(key, values.toString()); + sParameterMap.put(key, values.toString()); } public static String get(String key){ - return parameterMap.get(key); + return sParameterMap.get(key); } /** @return A list of values from an array stored as a string */ @@ -83,10 +82,10 @@ public class MCOptionUtils public static void save() { StringBuilder result = new StringBuilder(); - for(String key : parameterMap.keySet()) + for(String key : sParameterMap.keySet()) result.append(key) .append(':') - .append(parameterMap.get(key)) + .append(sParameterMap.get(key)) .append('\n'); try { @@ -114,7 +113,7 @@ public class MCOptionUtils * Listeners get notified of the change */ private static void setupFileObserver(){ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ - fileObserver = new FileObserver(new File(Tools.DIR_GAME_NEW + "/options.txt"), FileObserver.MODIFY) { + sFileObserver = new FileObserver(new File(Tools.DIR_GAME_NEW + "/options.txt"), FileObserver.MODIFY) { @Override public void onEvent(int i, @Nullable String s) { MCOptionUtils.load(); @@ -122,7 +121,7 @@ public class MCOptionUtils } }; }else{ - fileObserver = new FileObserver(Tools.DIR_GAME_NEW + "/options.txt", FileObserver.MODIFY) { + sFileObserver = new FileObserver(Tools.DIR_GAME_NEW + "/options.txt", FileObserver.MODIFY) { @Override public void onEvent(int i, @Nullable String s) { MCOptionUtils.load(); @@ -131,12 +130,12 @@ public class MCOptionUtils }; } - fileObserver.startWatching(); + sFileObserver.startWatching(); } /** Notify the option listeners */ public static void notifyListeners(){ - for(WeakReference weakReference : optionListeners){ + for(WeakReference weakReference : sOptionListeners){ MCOptionListener optionListener = weakReference.get(); if(optionListener == null) continue; @@ -146,16 +145,16 @@ public class MCOptionUtils /** Add an option listener, notice how we don't have a reference to it */ public static void addMCOptionListener(MCOptionListener listener){ - optionListeners.add(new WeakReference<>(listener)); + sOptionListeners.add(new WeakReference<>(listener)); } /** Remove a listener from existence, or at least, its reference here */ public static void removeMCOptionListener(MCOptionListener listener){ - for(WeakReference weakReference : optionListeners){ + for(WeakReference weakReference : sOptionListeners){ MCOptionListener optionListener = weakReference.get(); if(optionListener == null) continue; if(optionListener == listener){ - optionListeners.remove(weakReference); + sOptionListeners.remove(weakReference); return; } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/V117CompatUtil.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/V117CompatUtil.java index 3ef343f77..f7394eaf7 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/V117CompatUtil.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/V117CompatUtil.java @@ -95,15 +95,17 @@ public class V117CompatUtil { Log.i("V117CompatDebug",rawList); return new ArrayList<>(Arrays.asList(rawList.split(","))); } + private static String regenPackList(List packs) { if(packs.size()==0) return "[]"; - String ret = "["+packs.get(0); + StringBuilder ret = new StringBuilder("[" + packs.get(0)); for(int i = 1; i < packs.size(); i++) { - ret += ","+packs.get(i); + ret.append(",").append(packs.get(i)); } - ret += "]"; - return ret; + ret.append("]"); + return ret.toString(); } + public static void runCheck(String version, Activity ctx) throws Exception{ @@ -132,25 +134,25 @@ public class V117CompatUtil { Object lock = new Object(); AtomicInteger proceed = new AtomicInteger(0); ctx.runOnUiThread(() -> { - AlertDialog.Builder bldr = new AlertDialog.Builder(ctx); - bldr.setTitle(R.string.global_warinng); - bldr.setMessage(R.string.compat_117_message); - bldr.setPositiveButton(android.R.string.ok, (dialog, which) -> { + AlertDialog.Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle(R.string.global_warinng); + builder.setMessage(R.string.compat_117_message); + builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { proceed.set(1); synchronized (lock) { lock.notifyAll(); } dialog.dismiss(); }); - bldr.setNegativeButton(android.R.string.cancel, (dialog, which) -> { + builder.setNegativeButton(android.R.string.cancel, (dialog, which) -> { synchronized (lock) { lock.notifyAll(); } dialog.dismiss(); }); - bldr.setNeutralButton(R.string.compat_11x_playanyway, (dialog, which) -> { + builder.setNeutralButton(R.string.compat_11x_playanyway, (dialog, which) -> { proceed.set(2); synchronized (lock) { lock.notifyAll(); } dialog.dismiss(); }); - bldr.setCancelable(false); - bldr.show(); + builder.setCancelable(false); + builder.show(); }); synchronized (lock) { @@ -182,6 +184,7 @@ public class V117CompatUtil { throw new MinecraftDownloaderTask.SilentException(); } } + public static void copyResourcePack(String gameDir, AssetManager am) throws IOException { File resourcepacksDir = new File(gameDir,"resourcepacks"); if(!resourcepacksDir.exists()) resourcepacksDir.mkdirs(); diff --git a/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java index 7a3d20552..2781abeba 100644 --- a/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java +++ b/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java @@ -1,12 +1,8 @@ package org.lwjgl.glfw; -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.util.*; import android.os.Handler; import android.os.Looper; -import android.widget.*; + import net.kdt.pojavlaunch.*; import android.content.*; @@ -20,6 +16,9 @@ public class CallbackBridge { public static volatile int physicalWidth, physicalHeight; public static float mouseX, mouseY; public static StringBuilder DEBUG_STRING = new StringBuilder(); + private static boolean threadAttached; + public volatile static boolean holdingAlt, holdingCapslock, holdingCtrl, + holdingNumlock, holdingShift; public static void putMouseEventWithCoords(int button, float x, float y) { @@ -34,7 +33,7 @@ public class CallbackBridge { sendMouseKeycode(button, CallbackBridge.getCurrentMods(), isDown); } - private static boolean threadAttached; + public static void sendCursorPos(float x, float y) { if (!threadAttached) { threadAttached = CallbackBridge.nativeAttachThreadToOther(true, BaseMainActivity.isInputStackCall); @@ -158,43 +157,42 @@ public class CallbackBridge { private static native void nativeSendData(boolean isAndroid, int type, String data); */ - public volatile static boolean holdingAlt, holdingCapslock, holdingCtrl, - holdingNumlock, holdingShift; + public static int getCurrentMods() { int currMods = 0; if (holdingAlt) { - currMods |= LWJGLGLFWKeycode.GLFW_MOD_ALT; + currMods |= LwjglGlfwKeycode.GLFW_MOD_ALT; } if (holdingCapslock) { - currMods |= LWJGLGLFWKeycode.GLFW_MOD_CAPS_LOCK; + currMods |= LwjglGlfwKeycode.GLFW_MOD_CAPS_LOCK; } if (holdingCtrl) { - currMods |= LWJGLGLFWKeycode.GLFW_MOD_CONTROL; + currMods |= LwjglGlfwKeycode.GLFW_MOD_CONTROL; } if (holdingNumlock) { - currMods |= LWJGLGLFWKeycode.GLFW_MOD_NUM_LOCK; + currMods |= LwjglGlfwKeycode.GLFW_MOD_NUM_LOCK; } if (holdingShift) { - currMods |= LWJGLGLFWKeycode.GLFW_MOD_SHIFT; + currMods |= LwjglGlfwKeycode.GLFW_MOD_SHIFT; } return currMods; } public static void setModifiers(int keyCode, boolean isDown){ switch (keyCode){ - case LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT: + case LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT: CallbackBridge.holdingShift = isDown; return; - case LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL: + case LwjglGlfwKeycode.GLFW_KEY_LEFT_CONTROL: CallbackBridge.holdingCtrl = isDown; return; - case LWJGLGLFWKeycode.GLFW_KEY_LEFT_ALT: + case LwjglGlfwKeycode.GLFW_KEY_LEFT_ALT: CallbackBridge.holdingAlt = isDown; return; - case LWJGLGLFWKeycode.GLFW_KEY_CAPS_LOCK: + case LwjglGlfwKeycode.GLFW_KEY_CAPS_LOCK: CallbackBridge.holdingCapslock = isDown; return; - case LWJGLGLFWKeycode.GLFW_KEY_NUM_LOCK: + case LwjglGlfwKeycode.GLFW_KEY_NUM_LOCK: CallbackBridge.holdingNumlock = isDown; return; } @@ -211,7 +209,8 @@ public class CallbackBridge { private static native void nativeSendMouseButton(int button, int action, int mods); private static native void nativeSendScroll(double xoffset, double yoffset); private static native void nativeSendScreenSize(int width, int height); - + public static native void nativeSetWindowAttrib(int attrib, int value); + public static native boolean nativeIsGrabbing(); static { System.loadLibrary("pojavexec"); diff --git a/app_pojavlauncher/src/main/jni/input_bridge_v3.c b/app_pojavlauncher/src/main/jni/input_bridge_v3.c index b9df89e76..55cf5e1ae 100644 --- a/app_pojavlauncher/src/main/jni/input_bridge_v3.c +++ b/app_pojavlauncher/src/main/jni/input_bridge_v3.c @@ -363,3 +363,21 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendScroll(JNIEn JNIEXPORT void JNICALL Java_org_lwjgl_glfw_GLFW_nglfwSetShowingWindow(JNIEnv* env, jclass clazz, jlong window) { showingWindow = (long) window; } + +JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetWindowAttrib(JNIEnv* env, jclass clazz, jint attrib, jint value) { + if (!showingWindow) { + return; // nothing to do yet + } + + jclass glfwClazz = (*runtimeJNIEnvPtr_ANDROID)->FindClass(runtimeJNIEnvPtr_ANDROID, "org/lwjgl/glfw/GLFW"); + assert(glfwClazz != NULL); + jmethodID glfwMethod = (*runtimeJNIEnvPtr_ANDROID)->GetStaticMethodID(runtimeJNIEnvPtr_ANDROID, glfwMethod, "glfwSetWindowAttrib", "(JII)V"); + assert(glfwMethod != NULL); + + (*runtimeJNIEnvPtr_ANDROID)->CallStaticVoidMethod( + runtimeJNIEnvPtr_ANDROID, + glfwClazz, glfwMethod, + (jlong) showingWindow, attrib, value + ); +} + diff --git a/app_pojavlauncher/src/main/jniLibs/arm64-v8a/libvgpu.so b/app_pojavlauncher/src/main/jniLibs/arm64-v8a/libvgpu.so index b9eead908..bf536edf7 100644 Binary files a/app_pojavlauncher/src/main/jniLibs/arm64-v8a/libvgpu.so and b/app_pojavlauncher/src/main/jniLibs/arm64-v8a/libvgpu.so differ diff --git a/app_pojavlauncher/src/main/jniLibs/armeabi-v7a/libvgpu.so b/app_pojavlauncher/src/main/jniLibs/armeabi-v7a/libvgpu.so index a04bf59af..201cd7db5 100644 Binary files a/app_pojavlauncher/src/main/jniLibs/armeabi-v7a/libvgpu.so and b/app_pojavlauncher/src/main/jniLibs/armeabi-v7a/libvgpu.so differ diff --git a/app_pojavlauncher/src/main/jniLibs/x86/libvgpu.so b/app_pojavlauncher/src/main/jniLibs/x86/libvgpu.so index 033aeac1d..892f5a28b 100644 Binary files a/app_pojavlauncher/src/main/jniLibs/x86/libvgpu.so and b/app_pojavlauncher/src/main/jniLibs/x86/libvgpu.so differ diff --git a/app_pojavlauncher/src/main/jniLibs/x86_64/libvgpu.so b/app_pojavlauncher/src/main/jniLibs/x86_64/libvgpu.so index 68ed10f03..7acd39ade 100644 Binary files a/app_pojavlauncher/src/main/jniLibs/x86_64/libvgpu.so and b/app_pojavlauncher/src/main/jniLibs/x86_64/libvgpu.so differ diff --git a/app_pojavlauncher/src/main/res/anim/translate_left_side.xml b/app_pojavlauncher/src/main/res/anim/translate_left_side.xml deleted file mode 100644 index 962be1cc6..000000000 --- a/app_pojavlauncher/src/main/res/anim/translate_left_side.xml +++ /dev/null @@ -1,5 +0,0 @@ - - diff --git a/app_pojavlauncher/src/main/res/anim/translate_right_side.xml b/app_pojavlauncher/src/main/res/anim/translate_right_side.xml deleted file mode 100644 index 607d4f8d0..000000000 --- a/app_pojavlauncher/src/main/res/anim/translate_right_side.xml +++ /dev/null @@ -1,5 +0,0 @@ - - diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/ic_flatstyle.png b/app_pojavlauncher/src/main/res/drawable-hdpi/ic_flatstyle.png deleted file mode 100644 index 777730532..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-hdpi/ic_flatstyle.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/ic_map_rmb.png b/app_pojavlauncher/src/main/res/drawable-hdpi/ic_map_rmb.png deleted file mode 100644 index 5bdaa3296..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-hdpi/ic_map_rmb.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/ic_disable_gestures.png b/app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_disable_gestures.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-hdpi/ic_disable_gestures.png rename to app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_disable_gestures.png diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/freeform_opt.png b/app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_freeform.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-hdpi/freeform_opt.png rename to app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_freeform.png diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/ic_lib_check.png b/app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_lib_check.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-hdpi/ic_lib_check.png rename to app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_lib_check.png diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/ic_auto_ram.png b/app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_ram.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-hdpi/ic_auto_ram.png rename to app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_ram.png diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/tap_len.png b/app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_tap_length.png old mode 100755 new mode 100644 similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-hdpi/tap_len.png rename to app_pojavlauncher/src/main/res/drawable-hdpi/ic_setting_tap_length.png diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png b/app_pojavlauncher/src/main/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png deleted file mode 100644 index 9cdc25b45..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png b/app_pojavlauncher/src/main/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png deleted file mode 100644 index 276d48091..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-mdpi/btn_scale.png b/app_pojavlauncher/src/main/res/drawable-mdpi/ic_setting_btn_scale.png old mode 100755 new mode 100644 similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-mdpi/btn_scale.png rename to app_pojavlauncher/src/main/res/drawable-mdpi/ic_setting_btn_scale.png diff --git a/app_pojavlauncher/src/main/res/drawable-mdpi/jre_args.png b/app_pojavlauncher/src/main/res/drawable-mdpi/ic_setting_jre_args.png old mode 100755 new mode 100644 similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-mdpi/jre_args.png rename to app_pojavlauncher/src/main/res/drawable-mdpi/ic_setting_jre_args.png diff --git a/app_pojavlauncher/src/main/res/drawable-mdpi/mouse_pointer_1.png b/app_pojavlauncher/src/main/res/drawable-mdpi/ic_setting_mouse_pointer.png old mode 100755 new mode 100644 similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-mdpi/mouse_pointer_1.png rename to app_pojavlauncher/src/main/res/drawable-mdpi/ic_setting_mouse_pointer.png diff --git a/app_pojavlauncher/src/main/res/drawable-mdpi/rm_jre.png b/app_pojavlauncher/src/main/res/drawable-mdpi/rm_jre.png deleted file mode 100755 index dec16982a..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-mdpi/rm_jre.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png b/app_pojavlauncher/src/main/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png deleted file mode 100644 index 95c0168cd..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png b/app_pojavlauncher/src/main/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png deleted file mode 100644 index 569332abf..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-xhdpi/hide_sidebar.png b/app_pojavlauncher/src/main/res/drawable-xhdpi/ic_setting_hide_sidebar.png old mode 100755 new mode 100644 similarity index 100% rename from app_pojavlauncher/src/main/res/drawable-xhdpi/hide_sidebar.png rename to app_pojavlauncher/src/main/res/drawable-xhdpi/ic_setting_hide_sidebar.png diff --git a/app_pojavlauncher/src/main/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png b/app_pojavlauncher/src/main/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png deleted file mode 100644 index a01ac1030..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png b/app_pojavlauncher/src/main/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png deleted file mode 100644 index d3602d988..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png b/app_pojavlauncher/src/main/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png deleted file mode 100644 index 75085ce6d..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png b/app_pojavlauncher/src/main/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png deleted file mode 100644 index e2eb5bed2..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable/pointer.png b/app_pojavlauncher/src/main/res/drawable/ic_gamepad_pointer.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable/pointer.png rename to app_pojavlauncher/src/main/res/drawable/ic_gamepad_pointer.png diff --git a/app_pojavlauncher/src/main/res/drawable/logo.png b/app_pojavlauncher/src/main/res/drawable/ic_logo.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable/logo.png rename to app_pojavlauncher/src/main/res/drawable/ic_logo.png diff --git a/app_pojavlauncher/src/main/res/drawable/mouse_pointer.png b/app_pojavlauncher/src/main/res/drawable/ic_mouse_pointer.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable/mouse_pointer.png rename to app_pojavlauncher/src/main/res/drawable/ic_mouse_pointer.png diff --git a/app_pojavlauncher/src/main/res/drawable/ignore_notch.png b/app_pojavlauncher/src/main/res/drawable/ic_setting_ignore_notch.png old mode 100755 new mode 100644 similarity index 100% rename from app_pojavlauncher/src/main/res/drawable/ignore_notch.png rename to app_pojavlauncher/src/main/res/drawable/ic_setting_ignore_notch.png diff --git a/app_pojavlauncher/src/main/res/drawable/mouse_pointer_spd.png b/app_pojavlauncher/src/main/res/drawable/ic_setting_mouse_pointer_spd.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable/mouse_pointer_spd.png rename to app_pojavlauncher/src/main/res/drawable/ic_setting_mouse_pointer_spd.png diff --git a/app_pojavlauncher/src/main/res/drawable/resolution_scaler.png b/app_pojavlauncher/src/main/res/drawable/ic_setting_resolution_scaler.png old mode 100755 new mode 100644 similarity index 100% rename from app_pojavlauncher/src/main/res/drawable/resolution_scaler.png rename to app_pojavlauncher/src/main/res/drawable/ic_setting_resolution_scaler.png diff --git a/app_pojavlauncher/src/main/res/drawable/sign_in_background.png b/app_pojavlauncher/src/main/res/drawable/ic_setting_sign_in_background.png similarity index 100% rename from app_pojavlauncher/src/main/res/drawable/sign_in_background.png rename to app_pojavlauncher/src/main/res/drawable/ic_setting_sign_in_background.png diff --git a/app_pojavlauncher/src/main/res/drawable/ic_view_handle.xml b/app_pojavlauncher/src/main/res/drawable/ic_view_handle.xml new file mode 100644 index 000000000..f85c50284 --- /dev/null +++ b/app_pojavlauncher/src/main/res/drawable/ic_view_handle.xml @@ -0,0 +1,4 @@ + + + diff --git a/app_pojavlauncher/src/main/res/drawable/mouse_pointer_1.png b/app_pojavlauncher/src/main/res/drawable/mouse_pointer_1.png deleted file mode 100755 index e5bb2041d..000000000 Binary files a/app_pojavlauncher/src/main/res/drawable/mouse_pointer_1.png and /dev/null differ diff --git a/app_pojavlauncher/src/main/res/drawable/text_select_handle_left_material.xml b/app_pojavlauncher/src/main/res/drawable/text_select_handle_left_material.xml deleted file mode 100644 index b228d3f5a..000000000 --- a/app_pojavlauncher/src/main/res/drawable/text_select_handle_left_material.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - diff --git a/app_pojavlauncher/src/main/res/drawable/text_select_handle_right_material.xml b/app_pojavlauncher/src/main/res/drawable/text_select_handle_right_material.xml deleted file mode 100644 index acacbf678..000000000 --- a/app_pojavlauncher/src/main/res/drawable/text_select_handle_right_material.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - diff --git a/app_pojavlauncher/src/main/res/layout/main_with_customctrl.xml b/app_pojavlauncher/src/main/res/layout/activity_basemain.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/main_with_customctrl.xml rename to app_pojavlauncher/src/main/res/layout/activity_basemain.xml diff --git a/app_pojavlauncher/src/main/res/layout/control_mapping.xml b/app_pojavlauncher/src/main/res/layout/activity_custom_controls.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/control_mapping.xml rename to app_pojavlauncher/src/main/res/layout/activity_custom_controls.xml diff --git a/app_pojavlauncher/src/main/res/layout/import_control_layout.xml b/app_pojavlauncher/src/main/res/layout/activity_import_control.xml similarity index 97% rename from app_pojavlauncher/src/main/res/layout/import_control_layout.xml rename to app_pojavlauncher/src/main/res/layout/activity_import_control.xml index 4e5704f38..5aac9e3d1 100644 --- a/app_pojavlauncher/src/main/res/layout/import_control_layout.xml +++ b/app_pojavlauncher/src/main/res/layout/activity_import_control.xml @@ -12,7 +12,7 @@ android:layout_height="match_parent" android:elevation="-10dp" android:scaleType="centerCrop" - android:src="@drawable/sign_in_background" /> + android:src="@drawable/ic_setting_sign_in_background" /> + android:src="@drawable/ic_mouse_pointer" /> diff --git a/app_pojavlauncher/src/main/res/layout/launcher_main_v4.xml b/app_pojavlauncher/src/main/res/layout/activity_pojav_launcher.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/launcher_main_v4.xml rename to app_pojavlauncher/src/main/res/layout/activity_pojav_launcher.xml diff --git a/app_pojavlauncher/src/main/res/layout/launcher_login_v3.xml b/app_pojavlauncher/src/main/res/layout/activity_pojav_login.xml similarity index 73% rename from app_pojavlauncher/src/main/res/layout/launcher_login_v3.xml rename to app_pojavlauncher/src/main/res/layout/activity_pojav_login.xml index 3ea7c9697..e1ae586c3 100644 --- a/app_pojavlauncher/src/main/res/layout/launcher_login_v3.xml +++ b/app_pojavlauncher/src/main/res/layout/activity_pojav_login.xml @@ -19,7 +19,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:elevation="-10dp" - android:src="@drawable/sign_in_background" + android:src="@drawable/ic_setting_sign_in_background" android:scaleType="centerCrop" /> @@ -39,7 +39,7 @@ android:id="@+id/login_image_logo" android:layout_width="300dp" android:layout_height="48dp" - android:src="@drawable/logo" + android:src="@drawable/ic_logo" app:layout_constraintBottom_toTopOf="@+id/login_menu" app:layout_constraintEnd_toStartOf="@+id/guidelineLeft" @@ -82,57 +82,14 @@ app:layout_constraintTop_toTopOf="@+id/login_menu" app:layout_constraintVertical_bias="0.088" /> - - - - - - - - - - - + app:layout_constraintStart_toStartOf="@+id/login_edit_email" + app:layout_constraintTop_toBottomOf="@+id/login_edit_email" /> + app:layout_constraintStart_toStartOf="@id/login_switch_remember" + app:layout_constraintTop_toBottomOf="@id/login_switch_remember" /> @@ -190,4 +147,4 @@ app:layout_constraintStart_toStartOf="@+id/mineButton" app:layout_constraintTop_toBottomOf="@+id/mineButton" /> - \ No newline at end of file + diff --git a/app_pojavlauncher/src/main/res/layout/control_button_setting.xml b/app_pojavlauncher/src/main/res/layout/dialog_control_button_setting.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/control_button_setting.xml rename to app_pojavlauncher/src/main/res/layout/dialog_control_button_setting.xml diff --git a/app_pojavlauncher/src/main/res/layout/control_offset_preference_dialog.xml b/app_pojavlauncher/src/main/res/layout/dialog_control_offset_preference.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/control_offset_preference_dialog.xml rename to app_pojavlauncher/src/main/res/layout/dialog_control_offset_preference.xml diff --git a/app_pojavlauncher/src/main/res/layout/live_mouse_speed_editor.xml b/app_pojavlauncher/src/main/res/layout/dialog_live_mouse_speed_editor.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/live_mouse_speed_editor.xml rename to app_pojavlauncher/src/main/res/layout/dialog_live_mouse_speed_editor.xml diff --git a/app_pojavlauncher/src/main/res/layout/pvc_popup.xml b/app_pojavlauncher/src/main/res/layout/dialog_per_version_control.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/pvc_popup.xml rename to app_pojavlauncher/src/main/res/layout/dialog_per_version_control.xml diff --git a/app_pojavlauncher/src/main/res/layout/simple_account_list_holder.xml b/app_pojavlauncher/src/main/res/layout/dialog_select_account.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/simple_account_list_holder.xml rename to app_pojavlauncher/src/main/res/layout/dialog_select_account.xml diff --git a/app_pojavlauncher/src/main/res/layout/lmaintab_consolelog.xml b/app_pojavlauncher/src/main/res/layout/fragment_console_log.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/lmaintab_consolelog.xml rename to app_pojavlauncher/src/main/res/layout/fragment_console_log.xml diff --git a/app_pojavlauncher/src/main/res/layout/lmaintab_crashlog.xml b/app_pojavlauncher/src/main/res/layout/fragment_crash_log.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/lmaintab_crashlog.xml rename to app_pojavlauncher/src/main/res/layout/fragment_crash_log.xml diff --git a/app_pojavlauncher/src/main/res/layout/lmaintab_news.xml b/app_pojavlauncher/src/main/res/layout/fragment_news.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/lmaintab_news.xml rename to app_pojavlauncher/src/main/res/layout/fragment_news.xml diff --git a/app_pojavlauncher/src/main/res/layout/simple_account_list_item.xml b/app_pojavlauncher/src/main/res/layout/item_minecraft_account.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/simple_account_list_item.xml rename to app_pojavlauncher/src/main/res/layout/item_minecraft_account.xml diff --git a/app_pojavlauncher/src/main/res/layout/multirt_recyclable_view.xml b/app_pojavlauncher/src/main/res/layout/item_multirt_runtime.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/multirt_recyclable_view.xml rename to app_pojavlauncher/src/main/res/layout/item_multirt_runtime.xml diff --git a/app_pojavlauncher/src/main/res/layout/loggerview_layout.xml b/app_pojavlauncher/src/main/res/layout/view_logger.xml similarity index 100% rename from app_pojavlauncher/src/main/res/layout/loggerview_layout.xml rename to app_pojavlauncher/src/main/res/layout/view_logger.xml diff --git a/app_pojavlauncher/src/main/res/values/strings.xml b/app_pojavlauncher/src/main/res/values/strings.xml index c61c03b47..c8dfbe911 100644 --- a/app_pojavlauncher/src/main/res/values/strings.xml +++ b/app_pojavlauncher/src/main/res/values/strings.xml @@ -10,16 +10,12 @@ - Email or username - Password + Local username Keep me logged in Login - Login as offline account - Invalid username. Username must be in range of 3-16 characters, should only contains A-Z, a-z, 0-9 and underscore. This username already exist - Offline account can\'t include password! Microsoft login @@ -58,7 +54,7 @@ Connected - Offline + Local Ready to play Minecraft %s @@ -66,6 +62,7 @@ Downloading %s "Downloading %s (%.2f MB / %.2f MB)" Preparing to download resources + Minecraft can\'t be legally installed when logged in with a local account. Please switch to an online account to continue. Options Launch a mod installer (Forge, LabyMod, Fabric, etc...) diff --git a/app_pojavlauncher/src/main/res/values/styles.xml b/app_pojavlauncher/src/main/res/values/styles.xml index 0c537ead5..5067d8708 100644 --- a/app_pojavlauncher/src/main/res/values/styles.xml +++ b/app_pojavlauncher/src/main/res/values/styles.xml @@ -9,23 +9,4 @@ true @style/PreferenceThemeOverlay.v14.Material - - - - - diff --git a/app_pojavlauncher/src/main/res/xml/pref_control.xml b/app_pojavlauncher/src/main/res/xml/pref_control.xml index 982daf915..f5cc23764 100644 --- a/app_pojavlauncher/src/main/res/xml/pref_control.xml +++ b/app_pojavlauncher/src/main/res/xml/pref_control.xml @@ -9,7 +9,7 @@ @@ -21,7 +21,7 @@ app2:showSeekBarValue="true" app2:selectable="false" app2:seekBarIncrement="10" - app2:icon="@drawable/tap_len" /> + app2:icon="@drawable/ic_setting_tap_length" /> @@ -35,7 +35,7 @@ app2:showSeekBarValue="true" app2:selectable="false" app2:seekBarIncrement="5" - app2:icon="@drawable/btn_scale"/> + app2:icon="@drawable/ic_setting_btn_scale"/> @@ -48,7 +48,7 @@ android:key="mousescale" android:summary="@string/mcl_setting_subtitle_mousescale" android:title="@string/mcl_setting_title_mousescale" - app2:icon="@drawable/mouse_pointer_1" + app2:icon="@drawable/ic_setting_mouse_pointer" app2:selectable="false" app2:seekBarIncrement="5" app2:showSeekBarValue="true" /> @@ -56,7 +56,7 @@ android:key="mousespeed" android:summary="@string/mcl_setting_subtitle_mousespeed" android:title="@string/mcl_setting_title_mousespeed" - app2:icon="@drawable/mouse_pointer_spd" + app2:icon="@drawable/ic_setting_mouse_pointer_spd" app2:selectable="false" app2:seekBarIncrement="5" app2:showSeekBarValue="true" /> diff --git a/app_pojavlauncher/src/main/res/xml/pref_java.xml b/app_pojavlauncher/src/main/res/xml/pref_java.xml index a45405076..64d9a5164 100644 --- a/app_pojavlauncher/src/main/res/xml/pref_java.xml +++ b/app_pojavlauncher/src/main/res/xml/pref_java.xml @@ -11,7 +11,7 @@ + app2:icon="@drawable/ic_setting_hide_sidebar" /> diff --git a/app_pojavlauncher/src/main/res/xml/pref_video.xml b/app_pojavlauncher/src/main/res/xml/pref_video.xml index 8832a5838..255609284 100644 --- a/app_pojavlauncher/src/main/res/xml/pref_video.xml +++ b/app_pojavlauncher/src/main/res/xml/pref_video.xml @@ -18,7 +18,7 @@ android:key="ignoreNotch" android:summary="@string/mcl_setting_subtitle_ignore_notch" android:title="@string/mcl_setting_title_ignore_notch" - app2:icon="@drawable/ignore_notch" /> + app2:icon="@drawable/ic_setting_ignore_notch" /> + app2:icon="@drawable/ic_setting_resolution_scaler"/> \ No newline at end of file diff --git a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java index 702fa1155..1b15369b2 100644 --- a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java +++ b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java @@ -497,7 +497,7 @@ public class GLFW private static ArrayMap mGLFWWindowMap; public static boolean mGLFWIsGrabbing, mGLFWIsInputReady, mGLFWIsUseStackQueue = false; - public static final byte[] keyDownBuffer = new byte[316]; + public static final byte[] keyDownBuffer = new byte[317]; private static final String PROP_WINDOW_WIDTH = "glfwstub.windowWidth"; private static final String PROP_WINDOW_HEIGHT= "glfwstub.windowHeight"; public static long mainContext = 0; @@ -892,7 +892,7 @@ public class GLFW } public static int glfwGetWindowAttrib(@NativeType("GLFWwindow *") long window, int attrib) { - return internalGetWindow(window).windowAttribs.get(attrib); + return internalGetWindow(window).windowAttribs.getOrDefault(attrib, 0); } public static void glfwSetWindowAttrib(@NativeType("GLFWwindow *") long window, int attrib, int value) { @@ -995,9 +995,11 @@ public class GLFW win.width = mGLFWWindowWidth; win.height = mGLFWWindowHeight; - win.title = title; + win.windowAttribs.put(GLFW_HOVERED, 1); + win.windowAttribs.put(GLFW_VISIBLE, 1); + mGLFWWindowMap.put(ptr, win); mainContext = ptr; return ptr; @@ -1099,7 +1101,7 @@ public class GLFW break; case CallbackBridge.EVENT_TYPE_KEY: if (mGLFWKeyCallback != null) { - keyDownBuffer[dataArr[1]-32]=(byte)(int)dataArr[3]; + keyDownBuffer[Math.max(0, dataArr[1]-31)]=(byte)(int)dataArr[3]; mGLFWKeyCallback.invoke(ptr, dataArr[1], dataArr[2], dataArr[3], dataArr[4]); } break; @@ -1191,7 +1193,7 @@ public class GLFW } public static int glfwGetKey(@NativeType("GLFWwindow *") long window, int key) { - return keyDownBuffer[key-32]; + return keyDownBuffer[Math.max(0, key-31)]; } public static int glfwGetMouseButton(@NativeType("GLFWwindow *") long window, int button) {