Dummy Launcher (Need to set the main activity back to the default of TestStorageActivity to unpack the runtime before the DummyLauncher works.

This commit is contained in:
downthecrop 2023-07-28 11:57:44 -07:00
parent 844a90431b
commit dada3194c3
33 changed files with 979 additions and 196 deletions

136
AndroidManifest-back.xml Normal file
View file

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<queries>
<package android:name="net.kdt.pojavlaunch.ffmpeg" />
</queries>
<application
android:name=".PojavApplication"
android:allowBackup="true"
android:allowNativeHeapPointerTagging="false"
android:appCategory="game"
android:hasFragileUserData="true"
android:icon="@mipmap/ic_launcher"
android:isGame="true"
android:label="@string/app_name"
android:process=":launcher"
android:resizeableActivity="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme">
<activity
android:name=".DummyLauncher"
android:exported="true"
android:screenOrientation="landscape"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MissingStorageActivity"
android:exported="false" />
<meta-data
android:name="android.max_aspect"
android:value="ratio_float" />
<activity
android:name=".TestStorageActivity"
android:exported="true"
android:label="@string/app_short_name"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LauncherActivity"
android:label="@string/app_short_name" />
<activity
android:name=".ImportControlActivity"
android:configChanges="keyboard|keyboardHidden"
android:exported="true"
android:launchMode="singleInstance"
android:windowSoftInputMode="stateVisible">
<intent-filter
android:label="@string/import_control_label"
android:scheme="content"
tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/json" />
<data android:mimeType="text/json" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity
android:name=".FatalErrorActivity"
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
android:theme="@style/Theme.AppCompat.DayNight.Dialog" />
<activity
android:name=".ExitActivity"
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
android:theme="@style/Theme.AppCompat.DayNight.Dialog" />
<activity
android:name=".JavaGUILauncherActivity"
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|keyboard|navigation|uiMode"
android:screenOrientation="sensorLandscape" />
<activity
android:name=".CustomControlsActivity"
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
android:exported="false"
android:screenOrientation="sensorLandscape">
<intent-filter>
<action android:name=".CustomControlsActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|keyboard|navigation|uiMode"
android:launchMode="standard"
android:process=":game"
android:screenOrientation="sensorLandscape" />
<provider
android:name=".scoped.FolderProvider"
android:authorities="@string/storageProviderAuthorities"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
<service android:name=".services.ProgressService" />
<service
android:name=".services.GameService"
android:process=":game" />
</application>
</manifest>

View file

@ -199,4 +199,6 @@ dependencies {
// implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.0'
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.5.0'
}

View file

@ -40,13 +40,12 @@
android:value="ratio_float" />
<activity
android:name=".TestStorageActivity"
android:name=".DummyLauncher"
android:exported="true"
android:label="@string/app_short_name"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
@ -119,7 +118,4 @@
android:name=".services.GameService"
android:process=":game" />
</application>
<queries>
<package android:name="net.kdt.pojavlaunch.ffmpeg"/>
</queries>
</manifest>

View file

@ -1 +1 @@
1687691695196
1690130848255

View file

@ -1 +1 @@
1688133008591
1690130848291

View file

@ -1 +1 @@
1689180036097
1690130848323

View file

@ -0,0 +1,10 @@
{
"ip_management": "play.2009scape.org",
"ip_address": "play.2009scape.org",
"world": 1,
"server_port": 43594,
"wl_port": 43595,
"js5_port": 43595,
"mouseWheelZoom": true,
"pluginsFolder": "plugins"
}

View file

@ -10,8 +10,8 @@ import java.util.*;
import net.kdt.pojavlaunch.utils.*;
public class AWTCanvasView extends TextureView implements TextureView.SurfaceTextureListener, Runnable {
public static final int AWT_CANVAS_WIDTH = 720;
public static final int AWT_CANVAS_HEIGHT = 600;
public static final int AWT_CANVAS_WIDTH = 765;
public static final int AWT_CANVAS_HEIGHT = 503;
private static final int MAX_SIZE = 100;
private static final double NANOS = 1000000000.0;
private boolean mIsDestroyed = false;

View file

@ -0,0 +1,160 @@
package net.kdt.pojavlaunch;
import static net.kdt.pojavlaunch.Tools.launchGLJRE;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import net.kdt.pojavlaunch.value.MinecraftAccount;
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class DummyLauncher extends AppCompatActivity {
private FloatingActionButton fab;
private Button playHD;
private Button playSD;
private static final int FILE_SELECT_CODE_JSON = 0;
private static final int FILE_SELECT_CODE_ZIP = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dummy_launcher);
fab = findViewById(R.id.myFab);
playHD = findViewById(R.id.playHD);
playSD = findViewById(R.id.playSD);
playHD.setOnClickListener(view -> {
Log.i("downthecrop","hello from play HD touch");
// Launch MainActivity.java here and call runCraft()
Intent intent = new Intent(DummyLauncher.this, MainActivity.class);
startActivity(intent);
});
playSD.setOnClickListener(view -> {
Log.i("downthecrop","hello from play SD touch");
Intent intent = new Intent(DummyLauncher.this, JavaGUILauncherActivity.class);
startActivity(intent);
});
fab.setOnClickListener(view -> showBottomDialog());
}
@SuppressLint("ClickableViewAccessibility")
private void showBottomDialog() {
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.bottomsheetlayout);
dialog.show();
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.getWindow().setGravity(Gravity.BOTTOM);
final Button loadConfig = dialog.findViewById(R.id.loadConfig);
final Button loadPlugin = dialog.findViewById(R.id.loadPlugin);
loadConfig.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
showFileChooser(FILE_SELECT_CODE_JSON);
return true;
}
return false;
});
loadPlugin.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
showFileChooser(FILE_SELECT_CODE_ZIP);
return true;
}
return false;
});
}
private void showFileChooser(int requestCode) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
switch(requestCode){
case FILE_SELECT_CODE_JSON:
intent.setType("application/json");
intent.addCategory(Intent.CATEGORY_OPENABLE);
break;
case FILE_SELECT_CODE_ZIP:
intent.setType("application/zip");
intent.addCategory(Intent.CATEGORY_OPENABLE);
break;
default:
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
}
try {
startActivityForResult(
Intent.createChooser(intent, "Select a File to Upload"),
requestCode);
} catch (android.content.ActivityNotFoundException ex) {
// Potentially direct the user to the Market with a Dialog
Toast.makeText(this, "Please install a File Manager.",
Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FILE_SELECT_CODE_JSON) {
if (resultCode == RESULT_OK) {
Uri uri = data.getData();
// TODO: Change destination based on file type
File config = new File(Tools.DIR_DATA, "config.json");
try {
Log.d("TAG", "Starting copy: " + uri.getPath());
InputStream inputStream = getContentResolver().openInputStream(uri);
FileOutputStream fileOutputStream = new FileOutputStream(config);
byte buf[] = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
fileOutputStream.write(buf, 0, len);
}
Toast.makeText(this, "Config loaded. Please restart the app.",
Toast.LENGTH_SHORT).show();
fileOutputStream.close();
inputStream.close();
// TODO: unzip the plugin here
} catch (IOException e1) {
Log.d("error", "Error with file " + e1);
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
}

View file

@ -7,6 +7,7 @@ import android.content.ClipboardManager;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@ -24,6 +25,7 @@ import net.kdt.pojavlaunch.multirt.MultiRTUtils;
import net.kdt.pojavlaunch.multirt.Runtime;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.utils.JREUtils;
import net.kdt.pojavlaunch.utils.KeyEncoder;
import net.kdt.pojavlaunch.utils.MathUtils;
import org.lwjgl.glfw.CallbackBridge;
@ -149,23 +151,13 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
try {
placeMouseAt(CallbackBridge.physicalWidth / 2f, CallbackBridge.physicalHeight / 2f);
final File modFile = (File) getIntent().getExtras().getSerializable("modFile");
final String javaArgs = getIntent().getExtras().getString("javaArgs");
String jreName = LauncherPreferences.PREF_DEFAULT_RUNTIME;
if(modFile != null) {
int javaVersion = getJavaVersion(modFile);
if(javaVersion != -1) {
String autoselectRuntime = MultiRTUtils.getNearestJreName(javaVersion);
if (autoselectRuntime != null) jreName = autoselectRuntime;
}
}
final Runtime runtime = MultiRTUtils.forceReread(jreName);
mSkipDetectMod = getIntent().getExtras().getBoolean("skipDetectMod", false);
if(getIntent().getExtras().getBoolean("openLogOutput", false)) openLogOutput(null);
mSkipDetectMod = false;
if (mSkipDetectMod) {
new Thread(() -> launchJavaRuntime(runtime, modFile, javaArgs), "JREMainThread").start();
new Thread(() -> launchJavaRuntime(runtime, ""), "JREMainThread").start();
return;
}
@ -173,7 +165,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
openLogOutput(null);
new Thread(() -> {
try {
final int exit = doCustomInstall(runtime, modFile, javaArgs);
final int exit = launchJavaRuntime(runtime, "");
Logger.appendToLog(getString(R.string.toast_optifine_success));
if (exit != 0) return;
runOnUiThread(() -> {
@ -254,6 +246,14 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
return true;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getAction() == KeyEvent.ACTION_DOWN){
KeyEncoder.sendEncodedChar(event.getKeyCode(),(char)event.getUnicodeChar());
}
return true;
}
public void placeMouseAt(float x, float y) {
mMousePointerImageView.setX(x);
mMousePointerImageView.setY(y);
@ -287,33 +287,23 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
Toast.LENGTH_SHORT).show();
}
public int launchJavaRuntime(Runtime runtime, File modFile, String javaArgs) {
public int launchJavaRuntime(Runtime runtime, String javaArgs) {
runtime = MultiRTUtils.forceReread("Internal");
JREUtils.redirectAndPrintJRELog();
try {
List<String> javaArgList = new ArrayList<>();
File gamedir = new File(Tools.DIR_DATA);
// Enable Caciocavallo
Tools.getCacioJavaArgs(javaArgList,runtime.javaVersion == 8);
if (javaArgs != null) {
javaArgList.addAll(Arrays.asList(javaArgs.split(" ")));
} else {
javaArgList.add("-jar");
javaArgList.add(modFile.getAbsolutePath());
}
if (LauncherPreferences.PREF_JAVA_SANDBOX) {
Collections.reverse(javaArgList);
javaArgList.add("-Xbootclasspath/a:" + Tools.DIR_DATA + "/security/pro-grade.jar");
javaArgList.add("-Djava.security.manager=net.sourceforge.prograde.sm.ProGradeJSM");
javaArgList.add("-Djava.security.policy=" + Tools.DIR_DATA + "/security/java_sandbox.policy");
Collections.reverse(javaArgList);
}
javaArgList.add("-DconfigFile="+Tools.DIR_DATA + "/config.json");
javaArgList.add("-DpluginDir="+ Tools.DIR_DATA + "/plugins/");
javaArgList.add("-jar");
javaArgList.add(Tools.DIR_DATA+"/rt4.jar");
Logger.appendToLog("Info: Java arguments: " + Arrays.toString(javaArgList.toArray(new String[0])));
return JREUtils.launchJavaVM(this, runtime,null,javaArgList, LauncherPreferences.PREF_CUSTOM_JAVA_ARGS);
return JREUtils.launchJavaVM(this, runtime,gamedir,javaArgList, LauncherPreferences.PREF_CUSTOM_JAVA_ARGS);
} catch (Throwable th) {
Tools.showError(this, th, true);
return -1;
@ -324,7 +314,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
private int doCustomInstall(Runtime runtime, File modFile, String javaArgs) {
mSkipDetectMod = true;
return launchJavaRuntime(runtime, modFile, javaArgs);
return launchJavaRuntime(runtime, javaArgs);
}
public void toggleKeyboard(View view) {

View file

@ -1,6 +1,5 @@
package net.kdt.pojavlaunch;
import static net.kdt.pojavlaunch.Architecture.ARCH_X86;
import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_SUSTAINED_PERFORMANCE;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_USE_ALTERNATE_SURFACE;
@ -170,7 +169,6 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
case 1: openLogOutput(); break;
case 2: dialogSendCustomKey(); break;
case 3: adjustMouseSpeedLive(); break;
case 4: adjustGyroSensitivityLive(); break;
case 5: openCustomControls(); break;
}
drawerLayout.closeDrawers();
@ -187,8 +185,7 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
if (PREF_VIRTUAL_MOUSE_START) {
touchpad.post(() -> touchpad.switchState());
}
runCraft(finalVersion, mVersionInfo);
runCraft();
}catch (Throwable e){
Tools.showError(getApplicationContext(), e, true);
}
@ -317,40 +314,11 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
return Build.VERSION.SDK_INT >= 26;
}
private void runCraft(String versionId, JMinecraftVersionList.Version version) throws Throwable {
private void runCraft() throws Throwable {
if(Tools.LOCAL_RENDERER == null) {
Tools.LOCAL_RENDERER = LauncherPreferences.PREF_RENDERER;
}
MinecraftAccount minecraftAccount = PojavProfile.getCurrentProfileContent(this, null);
Logger.appendToLog("--------- beginning with launcher debug");
printLauncherInfo(versionId);
if (Tools.LOCAL_RENDERER.equals("vulkan_zink")) {
checkVulkanZinkIsSupported();
}
JREUtils.redirectAndPrintJRELog();
LauncherProfiles.update();
int requiredJavaVersion = 8;
if(version.javaVersion != null) requiredJavaVersion = version.javaVersion.majorVersion;
Tools.launchMinecraft(this, minecraftAccount, minecraftProfile, versionId, requiredJavaVersion);
}
private void printLauncherInfo(String gameVersion) {
Logger.appendToLog("Info: Launcher version: " + BuildConfig.VERSION_NAME);
Logger.appendToLog("Info: Architecture: " + Architecture.archAsString(Tools.DEVICE_ARCHITECTURE));
Logger.appendToLog("Info: Device model: " + Build.MANUFACTURER + " " +Build.MODEL);
Logger.appendToLog("Info: API version: " + Build.VERSION.SDK_INT);
Logger.appendToLog("Info: Selected Minecraft version: " + gameVersion);
Logger.appendToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\"");
}
private void checkVulkanZinkIsSupported() {
if (Tools.DEVICE_ARCHITECTURE == ARCH_X86
|| Build.VERSION.SDK_INT < 25
|| !getPackageManager().hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL)
|| !getPackageManager().hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION)) {
Logger.appendToLog("Error: Vulkan Zink renderer is not supported!");
throw new RuntimeException(getString(R.string. mcn_check_fail_vulkan_support));
}
Tools.launchGLJRE(this);
}
private void dialogSendCustomKey() {
@ -420,7 +388,6 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
if(touchCharInput != null) touchCharInput.switchKeyboardState();
}
int tmpMouseSpeed;
public void adjustMouseSpeedLive() {
AlertDialog.Builder b = new AlertDialog.Builder(this);
@ -431,12 +398,10 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
sb.setMax(275);
tmpMouseSpeed = (int) ((LauncherPreferences.PREF_MOUSESPEED*100));
sb.setProgress(tmpMouseSpeed-25);
tv.setText(getString(R.string.percent_format, tmpGyroSensitivity));
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
tmpMouseSpeed = i+25;
tv.setText(getString(R.string.percent_format, tmpGyroSensitivity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@ -456,47 +421,6 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
});
b.show();
}
int tmpGyroSensitivity;
public void adjustGyroSensitivityLive() {
if(!LauncherPreferences.PREF_ENABLE_GYRO) {
Toast.makeText(this, R.string.toast_turn_on_gyro, Toast.LENGTH_LONG).show();
return;
}
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle(R.string.preference_gyro_sensitivity_title);
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);
tmpGyroSensitivity = (int) ((LauncherPreferences.PREF_GYRO_SENSITIVITY*100));
sb.setProgress(tmpGyroSensitivity -25);
tv.setText(getString(R.string.percent_format, tmpGyroSensitivity));
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
tmpGyroSensitivity = i+25;
tv.setText(getString(R.string.percent_format, tmpGyroSensitivity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
b.setView(v);
b.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
LauncherPreferences.PREF_GYRO_SENSITIVITY = ((float) tmpGyroSensitivity)/100f;
LauncherPreferences.DEFAULT_PREF.edit().putInt("gyroSensitivity", tmpGyroSensitivity).apply();
dialogInterface.dismiss();
System.gc();
});
b.setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> {
dialogInterface.dismiss();
System.gc();
});
b.show();
}
private static void setUri(Context context, String input, Intent intent) {
if(input.startsWith("file:")) {
int truncLength = 5;

View file

@ -11,6 +11,7 @@ import static org.lwjgl.glfw.CallbackBridge.windowWidth;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.SurfaceTexture;
import android.os.Handler;
import android.os.Looper;
@ -20,6 +21,7 @@ import android.util.Log;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@ -48,6 +50,10 @@ import fr.spse.gamepad_remapper.RemapperView;
public class MinecraftGLSurface extends View implements GrabListener {
/* Gamepad object for gamepad inputs, instantiated on need */
private Gamepad mGamepad = null;
float startX = 0;
float startY = 0;
ScaleGestureDetector scaleGestureDetector;
/* The RemapperView.Builder object allows you to set which buttons to remap */
private final RemapperManager mInputManager = new RemapperManager(getContext(), new RemapperView.Builder(null)
.remapA(true)
@ -125,7 +131,6 @@ public class MinecraftGLSurface extends View implements GrabListener {
}
if(msg.what == MSG_DROP_ITEM_BUTTON_CHECK) {
if(CallbackBridge.isGrabbing()){
sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_Q);
mHandler.sendEmptyMessageDelayed(MSG_DROP_ITEM_BUTTON_CHECK, 600);
}
}
@ -146,7 +151,9 @@ public class MinecraftGLSurface extends View implements GrabListener {
}
/** Initialize the view and all its settings */
@SuppressLint("ClickableViewAccessibility")
public void start(){
scaleGestureDetector = new ScaleGestureDetector(this.getContext(), new ScaleListener());
if(LauncherPreferences.PREF_USE_ALTERNATE_SURFACE){
SurfaceView surfaceView = new SurfaceView(getContext());
mSurface = surfaceView;
@ -210,8 +217,6 @@ public class MinecraftGLSurface extends View implements GrabListener {
((ViewGroup)getParent()).addView(textureView);
}
}
@ -222,6 +227,10 @@ public class MinecraftGLSurface extends View implements GrabListener {
@Override
@SuppressWarnings("accessibility")
public boolean onTouchEvent(MotionEvent e) {
scaleGestureDetector.onTouchEvent(e);
Log.i("downthecrop","ya I still see these events");
// Kinda need to send this back to the layout
if(((ControlLayout)getParent()).getModifiable()) return false;
@ -243,7 +252,7 @@ public class MinecraftGLSurface extends View implements GrabListener {
CallbackBridge.mouseX = (e.getX() * mScaleFactor);
CallbackBridge.mouseY = (e.getY() * mScaleFactor);
//One android click = one MC click
if(mSingleTapDetector.onTouchEvent(e)){
if(mSingleTapDetector.onTouchEvent(e)){ // Touch Mode
CallbackBridge.putMouseEventWithCoords(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, CallbackBridge.mouseX, CallbackBridge.mouseY);
return true;
}
@ -254,6 +263,23 @@ public class MinecraftGLSurface extends View implements GrabListener {
switch (e.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
// Maybe here we do camera panning?
// Calculate the distance moved
float dx = (e.getX()) - startX;
float dy = (e.getY()) - startY;
// Do something with dx and dy here, like adjusting the camera position
try {
panCamera(dx, dy);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
// Update start position
startX = e.getX();
startY = e.getY();
int pointerCount = e.getPointerCount();
// In-menu interactions
@ -307,8 +333,8 @@ public class MinecraftGLSurface extends View implements GrabListener {
break;
case MotionEvent.ACTION_DOWN: // 0
sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, true);
sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_LEFT, false);
startX = e.getX();
startY = e.getY();
hudKeyHandled = handleGuiBar((int)e.getX(), (int) e.getY());
boolean isTouchInHotbar = hudKeyHandled != -1;
if (isTouchInHotbar) {
@ -339,6 +365,10 @@ public class MinecraftGLSurface extends View implements GrabListener {
break;
case MotionEvent.ACTION_UP: // 1
// End of drag, reset the start position
startX = 0;
startY = 0;
break;
case MotionEvent.ACTION_CANCEL: // 3
mShouldBeDown = false;
mCurrentPointerID = -1;
@ -394,6 +424,28 @@ public class MinecraftGLSurface extends View implements GrabListener {
return true;
}
private void panCamera(float dx, float dy) throws InterruptedException {
//Log.i("downthecrop-pan","dx: " +dx + " dy: " + dy);
final float threshold = 8.0f; // adjust this value as needed to control the sensitivity of the panning
// Check horizontal panning
if(dx > threshold) {
// Finger moved to the right, pan camera to the right
AWTInputBridge.sendKey((char)AWTInputEvent.VK_RIGHT, AWTInputEvent.VK_RIGHT);
} else if(dx < -threshold) {
AWTInputBridge.sendKey((char)AWTInputEvent.VK_LEFT, AWTInputEvent.VK_LEFT);
}
// Check vertical panning
if(dy > threshold) {
// Finger moved down, pan camera up
AWTInputBridge.sendKey((char)AWTInputEvent.VK_UP, AWTInputEvent.VK_UP);
} else if(dy < -threshold) {
// Finger moved up, pan camera down
AWTInputBridge.sendKey((char)AWTInputEvent.VK_DOWN, AWTInputEvent.VK_DOWN);
}
}
/**
* The event for mouse/joystick movements
*/
@ -481,7 +533,6 @@ public class MinecraftGLSurface extends View implements GrabListener {
//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;
}
@ -537,6 +588,32 @@ public class MinecraftGLSurface extends View implements GrabListener {
}
public static class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
Log.i("downthecrop","SCALE EVENT!");
float scaleFactor = detector.getScaleFactor();
if (scaleFactor > 1) { //Send F4 To Zoom Out
AWTInputBridge.sendKey((char)AWTInputEvent.VK_F3, AWTInputEvent.VK_F3);
} else { //116 F3 To Zoom In
AWTInputBridge.sendKey((char)AWTInputEvent.VK_F4,AWTInputEvent.VK_F4);
}
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
}
/** @return the hotbar key, given the position. -1 if no key are pressed */
public int handleGuiBar(int x, int y) {
@ -632,6 +709,10 @@ public class MinecraftGLSurface extends View implements GrabListener {
}
}
public int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
/** A small interface called when the listener is ready for the first time */
public interface SurfaceReadyListener {
void isReady();

View file

@ -45,6 +45,8 @@ import androidx.fragment.app.FragmentTransaction;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.kdt.pojavlaunch.extra.ExtraConstants;
import net.kdt.pojavlaunch.extra.ExtraCore;
import net.kdt.pojavlaunch.multirt.MultiRTUtils;
import net.kdt.pojavlaunch.multirt.Runtime;
import net.kdt.pojavlaunch.plugins.FFmpegPlugin;
@ -62,8 +64,11 @@ import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
import org.lwjgl.glfw.CallbackBridge;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -76,12 +81,17 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@SuppressWarnings("IOStreamConstructor")
public final class Tools {
public static final Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
public static String APP_NAME = "null";
public static final String RT4_MAIN_CLASS = "rt4.client";
public static final Gson GLOBAL_GSON = new GsonBuilder().setPrettyPrinting().create();
public static final String URL_HOME = "https://pojavlauncherteam.github.io";
@ -155,63 +165,24 @@ public final class Tools {
}
public static void launchMinecraft(final Activity activity, MinecraftAccount minecraftAccount,
MinecraftProfile minecraftProfile, String versionId, int versionJavaRequirement) throws Throwable {
int freeDeviceMemory = getFreeDeviceMemory(activity);
if(LauncherPreferences.PREF_RAM_ALLOCATION > freeDeviceMemory) {
Object memoryErrorLock = new Object();
activity.runOnUiThread(() -> {
androidx.appcompat.app.AlertDialog.Builder b = new androidx.appcompat.app.AlertDialog.Builder(activity)
.setMessage(activity.getString(R.string.memory_warning_msg, freeDeviceMemory ,LauncherPreferences.PREF_RAM_ALLOCATION))
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {synchronized(memoryErrorLock){memoryErrorLock.notifyAll();}})
.setOnCancelListener((i) -> {synchronized(memoryErrorLock){memoryErrorLock.notifyAll();}});
b.show();
});
synchronized (memoryErrorLock) {
memoryErrorLock.wait();
}
}
Runtime runtime = MultiRTUtils.forceReread(Tools.pickRuntime(minecraftProfile, versionJavaRequirement));
JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(versionId);
LauncherProfiles.update();
File gamedir = Tools.getGameDirPath(minecraftProfile);
public static void launchGLJRE(final Activity activity) throws Throwable {
Runtime runtime = MultiRTUtils.forceReread("Internal");
File gamedir = new File(Tools.DIR_DATA);
// Pre-process specific files
disableSplash(gamedir);
String[] launchArgs = getMinecraftClientArgs(minecraftAccount, versionInfo, gamedir);
// Select the appropriate openGL version
OldVersionsUtils.selectOpenGlVersion(versionInfo);
String launchClassPath = generateLaunchClassPath(versionInfo, versionId);
ExtraCore.setValue(ExtraConstants.OPEN_GL_VERSION, "2");
List<String> javaArgList = new ArrayList<>();
javaArgList.add("-Dorg.lwjgl.util.NoChecks=true");
getCacioJavaArgs(javaArgList, runtime.javaVersion == 8);
if (versionInfo.logging != null) {
String configFile = Tools.DIR_DATA + "/security/" + versionInfo.logging.client.file.id.replace("client", "log4j-rce-patch");
if (!new File(configFile).exists()) {
configFile = Tools.DIR_GAME_NEW + "/" + versionInfo.logging.client.file.id;
}
javaArgList.add("-Dlog4j.configurationFile=" + configFile);
}
javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(versionId, gamedir)));
javaArgList.add("-DpluginDir="+ Tools.DIR_DATA + "/plugins/");
javaArgList.add("-DconfigFile="+Tools.DIR_DATA + "/config.json");
javaArgList.add("-cp");
javaArgList.add(getLWJGL3ClassPath()+":"+Tools.DIR_DATA+"/rt4.jar");
//javaArgList.add(versionInfo.mainClass);
//javaArgList.addAll(Arrays.asList(launchArgs));
// ctx.appendlnToLog("full args: "+javaArgList.toString());
//javaArgList.add("HelloWorld"); //For hello.jar LWJGL test (red screen)
javaArgList.add("rt4.client"); //runescape mainclass
javaArgList.add(RT4_MAIN_CLASS);
String args = LauncherPreferences.PREF_CUSTOM_JAVA_ARGS;
if(Tools.isValidString(minecraftProfile.javaArgs)) args = minecraftProfile.javaArgs;
FFmpegPlugin.discover(activity);
JREUtils.launchJavaVM(activity, runtime, gamedir, javaArgList, args);
}
@ -764,10 +735,76 @@ public final class Tools {
File file = new File(nameOutput);
DownloadUtils.downloadFile(urlInput, file);
}
public interface DownloaderFeedback {
void updateProgress(int curr, int max);
}
public static class ZipTool
{
private ZipTool(){}
public static void zip(List<File> 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();
}
}
} finally {
zis.close();
}
}
}
public static boolean compareSHA1(File f, String sourceSHA) {
try {

View file

@ -7,6 +7,7 @@ import static net.kdt.pojavlaunch.prefs.LauncherPreferences.DEFAULT_PREF;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
@ -80,10 +81,21 @@ public class Touchpad extends FrameLayout implements GrabListener{
switch (action) {
case MotionEvent.ACTION_POINTER_DOWN: // 5
// Check if there are two fingers on the screen
if (event.getPointerCount() == 2) {
// Right-click event when a second finger touches the screen
// Simulating right-click by sending GLFW_MOUSE_BUTTON_RIGHT event
Log.i("downthecrop","Hi from a rightclick event!");
CallbackBridge.putMouseEventWithCoords(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, CallbackBridge.mouseX, CallbackBridge.mouseY);
}
mScrollLastInitialX = event.getX();
mScrollLastInitialY = event.getY();
break;
case MotionEvent.ACTION_DOWN:
mPrevX = x;
mPrevY = y;

View file

@ -3,16 +3,22 @@ package net.kdt.pojavlaunch.customcontrols.keyboard;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static org.lwjgl.glfw.CallbackBridge.sendKeyPress;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.kdt.pojavlaunch.AWTInputBridge;
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.utils.KeyEncoder;
/**
* This class is intended for sending characters used in chat via the virtual keyboard
@ -41,21 +47,18 @@ 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(mIsDoingInternalChanges)return;
if(mCharacterSender != null){
for(int i=0; i < lengthBefore; ++i){
mCharacterSender.sendBackspace();
}
for(int i=start, count = 0; count < lengthAfter; ++i){
mCharacterSender.sendChar(text.charAt(i));
++count;
}
if(lengthBefore == lengthAfter || lengthAfter == 30) return;
Log.i("TouchCharInput","New Event (before/after)!: "+ lengthBefore + " : " + lengthAfter);
boolean isBackSpace = (lengthBefore > lengthAfter);
if(isBackSpace) {
sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_BACKSPACE);
return;
}
char c = text.charAt(text.length()-1);
Log.i("TouchCharInput","New Event!: "+c);
if(mCharacterSender != null) {
sendKeyPress(c);
}
//Reset the keyboard state
if(text.length() < 1) clear();
}

View file

@ -45,7 +45,7 @@ public class LauncherPreferences {
public static boolean PREF_ARC_CAPES = false;
public static boolean PREF_USE_ALTERNATE_SURFACE = true;
public static boolean PREF_JAVA_SANDBOX = true;
public static int PREF_SCALE_FACTOR = 100;
public static int PREF_SCALE_FACTOR = 50;
public static boolean PREF_ENABLE_GYRO = false;
public static float PREF_GYRO_SENSITIVITY = 1f;
public static int PREF_GYRO_SAMPLE_RATE = 16;
@ -91,7 +91,7 @@ public class LauncherPreferences {
PREF_ARC_CAPES = DEFAULT_PREF.getBoolean("arc_capes",false);
PREF_USE_ALTERNATE_SURFACE = DEFAULT_PREF.getBoolean("alternate_surface", false);
PREF_JAVA_SANDBOX = DEFAULT_PREF.getBoolean("java_sandbox", true);
PREF_SCALE_FACTOR = DEFAULT_PREF.getInt("resolutionRatio", 100);
PREF_SCALE_FACTOR = DEFAULT_PREF.getInt("resolutionRatio", 50);
PREF_ENABLE_GYRO = DEFAULT_PREF.getBoolean("enableGyro", false);
PREF_GYRO_SENSITIVITY = ((float)DEFAULT_PREF.getInt("gyroSensitivity", 100))/100f;
PREF_GYRO_SAMPLE_RATE = DEFAULT_PREF.getInt("gyroSampleRate", 16);

View file

@ -65,8 +65,7 @@ public class AsyncAssetManager {
try {
Tools.copyAssetFile(ctx, "options.txt", Tools.DIR_GAME_NEW, false);
Tools.copyAssetFile(ctx, "default.json", Tools.CTRLMAP_PATH, false);
Tools.copyAssetFile(ctx, "launcher_profiles.json", Tools.DIR_GAME_NEW, false);
Tools.copyAssetFile(ctx, "launcher_profiles.json", Tools.DIR_GAME_NEW, false);
Tools.copyAssetFile(ctx,"resolv.conf",Tools.DIR_DATA, false);
} catch (IOException e) {
Log.e("AsyncAssetManager", "Failed to unpack critical components !");
@ -87,8 +86,12 @@ public class AsyncAssetManager {
unpackComponent(ctx, "security", true);
unpackComponent(ctx, "arc_dns_injector", true);
unpackComponent(ctx, "forge_installer", true);
Tools.copyAssetFile(ctx,"hello.jar",Tools.DIR_DATA, true);
Tools.copyAssetFile(ctx,"rt4.jar",Tools.DIR_DATA, true);
Tools.copyAssetFile(ctx,"config.json",Tools.DIR_DATA, true);
// Unzip the plugins for use.
extractAllPlugins(ctx); // Can comment this out to keep the plugins saved, rewrites them ever time it launches...
} catch (IOException e) {
Log.e("AsyncAssetManager", "Failed o unpack components !",e );
}
@ -96,6 +99,22 @@ public class AsyncAssetManager {
});
}
private static void extractAllPlugins(Context ctx) throws IOException {
String pluginsPath = "plugins"; // The folder where your plugins reside in the assets
AssetManager am = ctx.getAssets();
String[] plugins = am.list(pluginsPath);
if(plugins != null) {
for(String plugin : plugins) {
Tools.copyAssetFile(ctx, pluginsPath + "/" + plugin, Tools.DIR_DATA, true);
Tools.ZipTool.unzip(
new File(Tools.DIR_DATA + "/" + plugin),
new File(Tools.DIR_DATA + "/plugins/")
);
}
}
}
private static void unpackComponent(Context ctx, String component, boolean privateDirectory) throws IOException {
AssetManager am = ctx.getAssets();
String rootDir = privateDirectory ? Tools.DIR_DATA : Tools.DIR_GAME_HOME;

View file

@ -8,6 +8,7 @@ import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics;
import static net.kdt.pojavlaunch.Tools.shareLog;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_DUMP_SHADERS;
import android.annotation.SuppressLint;
import android.app.*;
import android.content.*;
import android.os.Build;
@ -256,6 +257,7 @@ public class JREUtils {
// return ldLibraryPath;
}
@SuppressLint("StringFormatInvalid")
public static int launchJavaVM(final Activity activity, final Runtime runtime, File gameDirectory, final List<String> JVMArgs, final String userArgsString) throws Throwable {
String runtimeHome = MultiRTUtils.getRuntimeHome(runtime.name).getAbsolutePath();
@ -315,7 +317,8 @@ public class JREUtils {
List<String> userArguments = parseJavaArguments(userArgumentsString);
String resolvFile;
resolvFile = new File(Tools.DIR_DATA,"resolv.conf").getAbsolutePath();
// TODO: MOVE THIS TO OUR NEW SETTINGS
LauncherPreferences.PREF_SCALE_FACTOR = 50;
ArrayList<String> overridableArguments = new ArrayList<>(Arrays.asList(
"-Djava.home=" + runtimeHome,
"-Djava.io.tmpdir=" + Tools.DIR_CACHE.getAbsolutePath(),

View file

@ -0,0 +1,112 @@
package net.kdt.pojavlaunch.utils;
import net.kdt.pojavlaunch.AWTInputBridge;
/*
About Key Events. Because the Android Spec doesn't require
soft keyboards to dispatch key events not all keyboard implementations
across Android will trigger these actions.
Currently we use the following function to translate keycodes for
special character, capital letters, and digits.
keycode 123 (F12) is used as a single digit capslock button which
when sent to the miniclient before a char will act accordingly.
*/
public class KeyEncoder {
static String specialChars = "/*!@#$%^&*()\"{}_[+:;=-_]'|\\?/<>,.";
static char modifier = 123;
static char backspaceAndroid = 67;
public static char backspaceUnicode = 8;
public static void sendEncodedChar(int keyCode, char iC){
System.out.println(keyCode);
if(keyCode == 75)
AWTInputBridge.sendKey((char)222,222);
else if(keyCode == backspaceAndroid){
AWTInputBridge.sendKey(backspaceUnicode,backspaceUnicode);
} else if(specialChars.contains(""+iC)){
// Send special character to client
char c = iC;
switch(c){
case '!':
c = '1';
break;
case '@':
c = '2';
break;
case '#':
c = '3';
break;
case '$':
c = '4';
break;
case '%':
c = '5';
break;
case '^':
c = '6';
break;
case '&':
c = '7';
break;
case '*':
c = '8';
break;
case '(':
c = '9';
break;
case ')':
c = '0';
break;
case '_':
c = '-';
break;
case '+':
c = '=';
break;
case '{':
c = '[';
break;
case '}':
c = ']';
break;
case ':':
c = ';';
break;
case '"':
c = '\'';
break;
case '<':
c = ',';
break;
case '>':
c = '.';
break;
case '?':
c = '/';
break;
case '|':
c = '\\';
break;
}
if(c != iC){
AWTInputBridge.sendKey(modifier,modifier);
}
AWTInputBridge.sendKey(c,c);
} else if(Character.isDigit(iC)){
AWTInputBridge.sendKey(iC,iC);
} else if (iC == Character.toUpperCase(iC)){
// We send F12 as a modifier to avoid needing to worry about shift.
// Client takes this modifier and does a toUpperCase().
AWTInputBridge.sendKey(modifier,modifier);
AWTInputBridge.sendKey(Character.toUpperCase(iC),Character.toUpperCase(iC));
} else if(iC == Character.toLowerCase(iC)){
AWTInputBridge.sendKey(Character.toUpperCase(iC),Character.toUpperCase(iC));
} else {
AWTInputBridge.sendKey(iC,keyCode);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#ffff"/>
<corners
android:topLeftRadius="40dp"
android:topRightRadius="40dp" />
<padding
android:left="10dp"
android:right="10dp"
android:top="10dp"
android:bottom="10dp"/>
<stroke
android:width="2dp"
android:color="#000"/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View file

@ -10,10 +10,12 @@
android:background="@drawable/no_focus_shown"
android:keepScreenOn="true">
<!--You can add padding here just paddingLeft, paddingRight-->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
>
<net.kdt.pojavlaunch.customcontrols.ControlLayout
android:id="@+id/main_control_layout"

View file

@ -0,0 +1,64 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#231c09"
tools:context=".DummyLauncher">
<ImageView
android:id="@+id/imageView4"
android:layout_width="0dp"
android:layout_height="31dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/plack" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/detail_select" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<Button
android:id="@+id/playHD"
android:layout_width="230dp"
android:layout_height="193dp"
android:layout_marginStart="64dp"
android:background="@android:color/transparent"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/imageView2"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/imageView2" />
<Button
android:id="@+id/playSD"
android:layout_width="339dp"
android:layout_height="191dp"
android:layout_marginEnd="-44dp"
android:background="@android:color/transparent"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/imageView2"
app:layout_constraintEnd_toEndOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/imageView2"
app:layout_constraintVertical_bias="0.504" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/myFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/imageView2"
tools:srcCompat="@tools:sample/avatars" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/dialoguebkg">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/createText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="5dp"
android:padding="8dp"
android:text="Settings"
android:textAlignment="viewStart"
android:textColor="#000000"
android:textSize="25dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/mouseSpeed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="Mouse Speed"
android:textColor="#000000"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="Auto Login"
android:textColor="#000000"
android:textSize="16sp" />
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:hint="Username"
android:background="#6F000000"
android:textColor="#ffffff"
android:padding="10dp"
android:textSize="16sp" />
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:hint="Password"
android:inputType="textPassword"
android:padding="10dp"
android:background="#6F000000"
android:textColor="#ffffff"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/plugins"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="Plugins"
android:textColor="#000000"
android:textSize="16sp"
android:textStyle="bold" />
<LinearLayout
android:id="@+id/plugin2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="Plugin1"
android:textColor="#000000"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/plugin1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="Plugin2"
android:textColor="#000000"
android:textSize="16sp" />
<Switch
android:id="@+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Switch" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:padding="10dp">
<Button
android:id="@+id/loadPlugin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="Load Plugin (Zipped)"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:padding="10dp">
<Button
android:id="@+id/loadConfig"
android:layout_width="197dp"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="Load Config File"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
</ScrollView>
<ImageView
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_gamepad_pointer" />
</LinearLayout>