From 84f97f3ccde12d10c8d217d8904ec3161be34d49 Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Tue, 17 Nov 2020 14:38:20 +0700 Subject: [PATCH] A lot of changes * Custom controls: - Rename classes - Add Dynamic position calculator for auto scale. TODO: document position variables * Source code - Abstracts MainActivity.java to prepare implement custom control. --- app/build.gradle | 2 + app/src/main/assets/about_en.txt | 1 + .../com/kdt/handleview/ActionPopupWindow.java | 8 +- .../java/com/kdt/handleview/HandleView.java | 4 +- .../handleview/SelectionEndHandleView.java | 2 +- .../net/kdt/pojavlaunch/AWTCanvasView.java | 2 +- .../kdt/pojavlaunch/AndroidLWJGLKeycode.java | 4 +- .../net/kdt/pojavlaunch/BaseMainActivity.java | 1230 +++++++++++++++ .../pojavlaunch/CustomControlsActivity.java | 6 +- .../pojavlaunch/JavaGUILauncherActivity.java | 2 +- .../net/kdt/pojavlaunch/MainActivity.java | 1334 +---------------- .../net/kdt/pojavlaunch/PojavApplication.java | 2 +- .../kdt/pojavlaunch/PojavLoginActivity.java | 10 +- .../main/java/net/kdt/pojavlaunch/Tools.java | 28 +- .../customcontrols/ControlButton.java | 216 +-- .../customcontrols/ControlData.java | 98 ++ ...ControlsLayout.java => ControlLayout.java} | 28 +- .../customcontrols/ControlView.java | 145 -- .../customcontrols/CustomControls.java | 38 +- .../customcontrols/DynamicControlButton.java | 6 - .../customcontrols/DynamicControlData.java | 77 + .../tasks/MinecraftDownloaderTask.java | 2 +- .../net/kdt/pojavlaunch/utils/JSONUtils.java | 20 + .../java/org/lwjgl/glfw/CallbackBridge.java | 8 +- 24 files changed, 1682 insertions(+), 1591 deletions(-) create mode 100644 app/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java create mode 100644 app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlData.java rename app/src/main/java/net/kdt/pojavlaunch/customcontrols/{ControlsLayout.java => ControlLayout.java} (68%) delete mode 100644 app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlView.java delete mode 100644 app/src/main/java/net/kdt/pojavlaunch/customcontrols/DynamicControlButton.java create mode 100644 app/src/main/java/net/kdt/pojavlaunch/customcontrols/DynamicControlData.java create mode 100644 app/src/main/java/net/kdt/pojavlaunch/utils/JSONUtils.java diff --git a/app/build.gradle b/app/build.gradle index 25435f918..06e3c3676 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -73,5 +73,7 @@ dependencies { implementation 'org.tukaani:xz:1.8' + implementation 'net.objecthunter:exp4j:0.4.8' + implementation fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/app/src/main/assets/about_en.txt b/app/src/main/assets/about_en.txt index caf95a9b4..8478b0963 100644 --- a/app/src/main/assets/about_en.txt +++ b/app/src/main/assets/about_en.txt @@ -11,6 +11,7 @@ * Third party licenses:
• Apache Commons Compress (unknown or Apache License 2.0).
+ • exp4j: Apache License 2.0.
• gl4es: MIT License.
• LegacyLauncher: (unknown license).
• OpenJDK: GNU GPLv2 License.
diff --git a/app/src/main/java/com/kdt/handleview/ActionPopupWindow.java b/app/src/main/java/com/kdt/handleview/ActionPopupWindow.java index 2f94c36a6..3c3134752 100644 --- a/app/src/main/java/com/kdt/handleview/ActionPopupWindow.java +++ b/app/src/main/java/com/kdt/handleview/ActionPopupWindow.java @@ -120,7 +120,7 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe alert.setPositiveButton(android.R.string.ok, null); alert.setNegativeButton(android.R.string.cancel, null); final AlertDialog dialog = alert.create(); - final ControlButton properties = mHandleView.mView.getProperties(); + final ControlData properties = mHandleView.mView.getProperties(); dialog.setOnShowListener(new DialogInterface.OnShowListener() { @@ -134,7 +134,7 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe final Spinner spinnerKeycode = dialog.findViewById(R.id.controlsetting_spinner_lwjglkeycode); ArrayAdapter adapter = new ArrayAdapter(view.getContext(), android.R.layout.simple_spinner_item); - String[] oldSpecialArr = ControlButton.buildSpecialButtonArray(); + String[] oldSpecialArr = ControlData.buildSpecialButtonArray(); String[] specialArr = new String[oldSpecialArr.length]; for (int i = 0; i < specialArr.length; i++) { specialArr[i] = "SPECIAL_" + oldSpecialArr[i]; @@ -145,7 +145,7 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice); spinnerKeycode.setAdapter(adapter); if (properties.keycode < 0) { - spinnerKeycode.setSelection(properties.keycode + 2); + spinnerKeycode.setSelection(properties.keycode + 5); } else { spinnerKeycode.setSelection(AndroidLWJGLKeycode.getIndexByLWJGLKey(properties.keycode + 2)); } @@ -194,7 +194,7 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe @Override public void onClick(DialogInterface p1, int p2) { - ControlsLayout layout = ((ControlsLayout) mHandleView.mView.getParent()); + ControlLayout layout = ((ControlLayout) mHandleView.mView.getParent()); layout.removeControlButton(mHandleView.mView); } }); diff --git a/app/src/main/java/com/kdt/handleview/HandleView.java b/app/src/main/java/com/kdt/handleview/HandleView.java index 28c050eea..fcc2dbfc5 100644 --- a/app/src/main/java/com/kdt/handleview/HandleView.java +++ b/app/src/main/java/com/kdt/handleview/HandleView.java @@ -59,7 +59,7 @@ public abstract class HandleView extends View implements ViewPositionListener, V private Runnable mActionPopupShower; // Minimum touch target size for handles private int mMinSize; - protected ControlView mView; + protected ControlButton mView; // MOD: Addition. Save old size of parent private int mDownWidth, mDownHeight; @@ -92,7 +92,7 @@ public abstract class HandleView extends View implements ViewPositionListener, V return -1; } - public HandleView(ControlView view) { + public HandleView(ControlButton view) { super(view.getContext()); mView = view; diff --git a/app/src/main/java/com/kdt/handleview/SelectionEndHandleView.java b/app/src/main/java/com/kdt/handleview/SelectionEndHandleView.java index 721bdc401..85a078335 100644 --- a/app/src/main/java/com/kdt/handleview/SelectionEndHandleView.java +++ b/app/src/main/java/com/kdt/handleview/SelectionEndHandleView.java @@ -27,7 +27,7 @@ import net.kdt.pojavlaunch.customcontrols.*; public class SelectionEndHandleView extends HandleView { - public SelectionEndHandleView(ControlView view) { + public SelectionEndHandleView(ControlButton view) { super(view); } diff --git a/app/src/main/java/net/kdt/pojavlaunch/AWTCanvasView.java b/app/src/main/java/net/kdt/pojavlaunch/AWTCanvasView.java index b1907bc42..56061ea17 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/AWTCanvasView.java +++ b/app/src/main/java/net/kdt/pojavlaunch/AWTCanvasView.java @@ -86,7 +86,7 @@ public class AWTCanvasView extends TextureView implements TextureView.SurfaceTex canvas.drawRGB(0, 0, 0); if (!attached) { - attached = CallbackBridge.nativeAttachThreadToOther(true, false, MainActivity.isInputStackCall); + attached = CallbackBridge.nativeAttachThreadToOther(true, false, BaseMainActivity.isInputStackCall); } else { int[] rgbArray = JREUtils.renderAWTScreenFrame(/* canvas, mWidth, mHeight */); mDrawing = rgbArray != null; diff --git a/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java b/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java index 552d96872..5c0f9de4b 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java +++ b/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java @@ -168,7 +168,7 @@ public class AndroidLWJGLKeycode { return androidKeyNameArray; } - public static void execKey(MainActivity mainActivity, KeyEvent keyEvent, int i, boolean isDown) { + public static void execKey(BaseMainActivity mainActivity, KeyEvent keyEvent, int i, boolean isDown) { for (Map.Entry perKey : androidToLwjglMap.entrySet()) { if (i == 1 && (keyEvent.getSource() == InputDevice.SOURCE_MOUSE)) { // Right mouse detection @@ -207,7 +207,7 @@ public class AndroidLWJGLKeycode { } } - public static void execKeyIndex(MainActivity mainActivity, int index) { + public static void execKeyIndex(BaseMainActivity mainActivity, int index) { mainActivity.sendKeyPress(getKeyIndex(index)); } diff --git a/app/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java b/app/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java new file mode 100644 index 000000000..968ed332f --- /dev/null +++ b/app/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java @@ -0,0 +1,1230 @@ +package net.kdt.pojavlaunch; + +import android.app.*; +import android.content.*; +import android.graphics.*; +import android.os.*; +import android.support.design.widget.*; +import android.support.v4.widget.*; +import android.util.*; +import android.view.*; +import android.view.View.*; +import android.view.inputmethod.*; +import android.widget.*; +import com.kdt.pointer.*; +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import net.kdt.pojavlaunch.customcontrols.*; +import net.kdt.pojavlaunch.prefs.*; +import net.kdt.pojavlaunch.utils.*; +import org.lwjgl.glfw.*; + +public class BaseMainActivity extends LoggableActivity implements OnTouchListener { + public static volatile ClipboardManager GLOBAL_CLIPBOARD; + + public static final String initText = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "; + volatile public static boolean isInputStackCall; + + private static 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}; + + private boolean rightOverride = false; + private int scaleFactor = 1; + private int fingerStillThreshold = 8; + private int initialX; + private int initialY; + private boolean mIsResuming = false; + private static final int MSG_LEFT_MOUSE_BUTTON_CHECK = 1028; + private static final int MSG_DROP_ITEM_BUTTON_CHECK = 1029; + private static boolean triggeredLeftMouseButton = false; + private Handler theHandler = new Handler() { + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_LEFT_MOUSE_BUTTON_CHECK: { + int x = CallbackBridge.mouseX; + int y = CallbackBridge.mouseY; + if (CallbackBridge.isGrabbing() && + Math.abs(initialX - x) < fingerStillThreshold && + Math.abs(initialY - y) < fingerStillThreshold) { + triggeredLeftMouseButton = true; + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); + } + } break; + case MSG_DROP_ITEM_BUTTON_CHECK: { + sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, true); + } break; + } + } + }; + private MinecraftGLView minecraftGLView; + private int guiScale; + private DisplayMetrics displayMetrics; + public boolean hiddenTextIgnoreUpdate = true; + public String hiddenTextContents = initText; + + private LinearLayout touchPad; + private ImageView mousePointer; + //private EditText hiddenEditor; + // private ViewGroup overlayView; + private MCProfile.Builder mProfile; + + private DrawerLayout drawerLayout; + private NavigationView navDrawer; + + private LinearLayout contentLog; + private TextView textLog; + private ScrollView contentScroll; + private ToggleButton toggleLog; + private GestureDetector gestureDetector; + + private TextView debugText; + + private PointerOreoWrapper pointerSurface; + private View.OnTouchListener pointerCaptureListener; + + // private String mQueueText = new String(); + + protected JMinecraftVersionList.Version mVersionInfo; + + private View.OnTouchListener glTouchListener; + + private File logFile; + private PrintStream logStream; + + /* + private LinearLayout contentCanvas; + private AWTSurfaceView contentCanvasView; + */ + private boolean lastEnabled = false; + private boolean lastGrab = false; + private boolean isExited = false; + private boolean isLogAllow = false; + // private int navBarHeight = 40; + + // private static Collection rsaPkcs1List; + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + try { + // FIXME: is it safe fot multi thread? + GLOBAL_CLIPBOARD = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); + + logFile = new File(Tools.MAIN_PATH, "latestlog.txt"); + logFile.delete(); + logFile.createNewFile(); + logStream = new PrintStream(logFile.getAbsolutePath()); + + Tools.setFullscreen(this); + + mProfile = PojavProfile.getCurrentProfileContent(this); + mVersionInfo = Tools.getVersionInfo(mProfile.getVersion()); + // Minecraft 1.12.x special case: use indirect char pipe + CallbackBridge.isMinecraft1p12 = mVersionInfo.assets.startsWith("1.12"); + + setTitle("Minecraft " + mProfile.getVersion()); + + // Minecraft 1.13+ + isInputStackCall = mVersionInfo.arguments != null; + + this.displayMetrics = Tools.getDisplayMetrics(this); + CallbackBridge.windowWidth = displayMetrics.widthPixels / scaleFactor; + CallbackBridge.windowHeight = displayMetrics.heightPixels / scaleFactor; + System.out.println("WidthHeight: " + CallbackBridge.windowWidth + ":" + CallbackBridge.windowHeight); + + gestureDetector = new GestureDetector(this, new SingleTapConfirm()); + + // Menu + drawerLayout = (DrawerLayout) findViewById(R.id.main_drawer_options); + + navDrawer = findViewById(R.id.main_navigation_view); + navDrawer.setNavigationItemSelectedListener( + new NavigationView.OnNavigationItemSelectedListener() { + @Override + public boolean onNavigationItemSelected(MenuItem menuItem) { + switch (menuItem.getItemId()) { + case R.id.nav_forceclose: dialogForceClose(BaseMainActivity.this); + break; + case R.id.nav_viewlog: openLogOutput(); + break; + case R.id.nav_debug: toggleDebug(); + break; + case R.id.nav_customkey: dialogSendCustomKey(); + } + //Toast.makeText(MainActivity.this, menuItem.getTitle() + ":" + menuItem.getItemId(), Toast.LENGTH_SHORT).show(); + + drawerLayout.closeDrawers(); + return true; + } + }); + + // this.overlayView = (ViewGroup) findViewById(R.id.main_control_overlay); + + //this.hiddenEditor = findViewById(R.id.hiddenTextbox); + + // Mouse pointer part + //this.mouseToggleButton = findButton(R.id.control_togglemouse); + this.touchPad = (LinearLayout) findViewById(R.id.main_touchpad); + this.mousePointer = (ImageView) findViewById(R.id.main_mouse_pointer); + + this.contentLog = (LinearLayout) findViewById(R.id.content_log_layout); + this.contentScroll = (ScrollView) findViewById(R.id.content_log_scroll); + this.textLog = (TextView) contentScroll.getChildAt(0); + this.toggleLog = (ToggleButton) findViewById(R.id.content_log_toggle_log); + this.toggleLog.setChecked(false); + // this.textLogBehindGL = (TextView) findViewById(R.id.main_log_behind_GL); + // this.textLogBehindGL.setTypeface(Typeface.MONOSPACE); + + this.textLog.setTypeface(Typeface.MONOSPACE); + this.toggleLog.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener(){ + + @Override + public void onCheckedChanged(CompoundButton button, boolean isChecked) + { + isLogAllow = isChecked; + appendToLog(""); + } + }); + + this.debugText = (TextView) findViewById(R.id.content_text_debug); + + this.minecraftGLView = (MinecraftGLView) findViewById(R.id.main_game_render_view); + + ControlData[] specialButtons = ControlData.getSpecialButtons(); + specialButtons[0].specialButtonListener = new View.OnClickListener(){ + @Override + public void onClick(View view) { + showKeyboard(); + } + }; + + // toggleGui(null); + this.drawerLayout.closeDrawers(); + + AndroidLWJGLKeycode.isBackspaceAfterChar = mVersionInfo.minimumLauncherVersion >= 18; + + placeMouseAt(CallbackBridge.windowWidth / 2, CallbackBridge.windowHeight / 2); + new Thread(new Runnable(){ + + private boolean isCapturing = false; + @Override + public void run() + { + while (!isExited) { + mousePointer.post(new Runnable(){ + + @Override + public void run() + { + if (lastGrab && !CallbackBridge.isGrabbing() && lastEnabled) { + touchPad.setVisibility(View.VISIBLE); + placeMouseAt(CallbackBridge.windowWidth / 2, CallbackBridge.windowHeight / 2); + } + + if (!CallbackBridge.isGrabbing()) { + lastEnabled = touchPad.getVisibility() == View.VISIBLE; + } else if (touchPad.getVisibility() != View.GONE) { + touchPad.setVisibility(View.GONE); + } + + if (isPointerCaptureSupported()) { + if (!CallbackBridge.isGrabbing() && isCapturing) { + pointerSurface.releaseCapture(); // minecraftGLView.releasePointerCapture(); + isCapturing = false; + } else if (CallbackBridge.isGrabbing() && !isCapturing) { + minecraftGLView.requestFocus(); + pointerSurface.requestCapture(); // minecraftGLView.requestPointerCapture(); + isCapturing = true; + } + } + + lastGrab = CallbackBridge.isGrabbing(); + } + }); + + try { + Thread.sleep(100); + } catch (Throwable th) {} + } + } + }).start(); + + 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(); + + float mouseX = mousePointer.getTranslationX(); + float mouseY = mousePointer.getTranslationY(); + + if (gestureDetector.onTouchEvent(event)) { + + CallbackBridge.sendCursorPos((int) mouseX, (int) mouseY); + CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT); + if (!rightOverride) { + CallbackBridge.mouseLeft = true; + } + + } else { + switch (action) { + case MotionEvent.ACTION_UP: // 1 + case MotionEvent.ACTION_CANCEL: // 3 + case MotionEvent.ACTION_POINTER_UP: // 6 + if (!rightOverride) { + CallbackBridge.mouseLeft = false; + } + break; + case MotionEvent.ACTION_MOVE: // 2 + mouseX = Math.max(0, Math.min(CallbackBridge.windowWidth, mouseX + x - prevX)); + mouseY = Math.max(0, Math.min(CallbackBridge.windowHeight, mouseY + y - prevY)); + placeMouseAt(mouseX, mouseY); + + CallbackBridge.sendCursorPos((int) mouseX, (int) mouseY); + /* + if (!CallbackBridge.isGrabbing()) { + CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, isLeftMouseDown); + CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, 0, isRightMouseDown); + } + */ + break; + } + } + prevX = x; + prevY = y; + + debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); + + return true; + } + }); + + // System.loadLibrary("Regal"); + + minecraftGLView.setFocusable(true); + minecraftGLView.setFocusableInTouchMode(true); + // minecraftGLView.setEGLContextClientVersion(2); + + glTouchListener = new OnTouchListener(){ + private boolean isTouchInHotbar = false; + private int hotbarX, hotbarY; + private int scrollInitialX, scrollInitialY; + @Override + public boolean onTouch(View p1, MotionEvent e) + { + // System.out.println("Pre touch, isTouchInHotbar=" + Boolean.toString(isTouchInHotbar) + ", action=" + MotionEvent.actionToString(e.getActionMasked())); + int x = ((int) e.getX()) / scaleFactor; + int y = ((int) e.getY()) / scaleFactor; + int hudKeyHandled = handleGuiBar(x, y); + if (!CallbackBridge.isGrabbing() && gestureDetector.onTouchEvent(e)) { + if (hudKeyHandled != -1) { + sendKeyPress(hudKeyHandled); + } else { + CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, x, y); + if (!rightOverride) { + CallbackBridge.mouseLeft = true; + } + } + } else { + switch (e.getActionMasked()) { + case MotionEvent.ACTION_DOWN: // 0 + case MotionEvent.ACTION_POINTER_DOWN: // 5 + CallbackBridge.sendPrepareGrabInitialPos(); + + isTouchInHotbar = hudKeyHandled != -1; + if (isTouchInHotbar) { + sendKeyPress(hudKeyHandled, 0, true); + hotbarX = x; + hotbarY = y; + + theHandler.sendEmptyMessageDelayed(BaseMainActivity.MSG_DROP_ITEM_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); + } else { + CallbackBridge.mouseX = x; + CallbackBridge.mouseY = y; + CallbackBridge.sendCursorPos(x, y); + if (!rightOverride) { + CallbackBridge.mouseLeft = true; + } + + if (CallbackBridge.isGrabbing()) { + // It cause hold left mouse while moving camera + // CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, (byte) 1, x, y); + initialX = x; + initialY = y; + theHandler.sendEmptyMessageDelayed(BaseMainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); + } + + scrollInitialX = x; + scrollInitialY = y; + } + break; + + case MotionEvent.ACTION_UP: // 1 + case MotionEvent.ACTION_POINTER_UP: // 6 + case MotionEvent.ACTION_CANCEL: // 3 + if (!isTouchInHotbar) { + CallbackBridge.mouseX = x; + CallbackBridge.mouseY = y; + + // -TODO uncomment after fix wrong trigger + // CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, (byte) 0, x, y); + CallbackBridge.sendCursorPos(x, y); + if (!rightOverride) { + CallbackBridge.mouseLeft = false; + } + } + + if (CallbackBridge.isGrabbing()) { + // System.out.println((String) ("[Math.abs(" + initialX + " - " + x + ") = " + Math.abs(initialX - x) + "] < " + fingerStillThreshold)); + // System.out.println((String) ("[Math.abs(" + initialY + " - " + y + ") = " + Math.abs(initialY - y) + "] < " + fingerStillThreshold)); + if (isTouchInHotbar && Math.abs(hotbarX - x) < fingerStillThreshold && Math.abs(hotbarY - y) < fingerStillThreshold) { + sendKeyPress(hudKeyHandled, 0, false); + } else if (!triggeredLeftMouseButton && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); + } + if (!isTouchInHotbar) { + if (triggeredLeftMouseButton) { + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, false); + } + triggeredLeftMouseButton = false; + theHandler.removeMessages(BaseMainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK); + } else { + sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, false); + theHandler.removeMessages(MSG_DROP_ITEM_BUTTON_CHECK); + } + } + + break; +/* + case MotionEvent.ACTION_POINTER_DOWN: // 5 + CallbackBridge.sendScroll(x - scrollInitialX, y - scrollInitialY); + scrollInitialX = x; + scrollInitialY = y; + break; + + case MotionEvent.ACTION_POINTER_UP: // 6 + scrollInitialX = x; + scrollInitialY = y; + break; + */ + case MotionEvent.ACTION_MOVE: + if (!isTouchInHotbar) { + CallbackBridge.mouseX = x; + CallbackBridge.mouseY = y; + + CallbackBridge.sendCursorPos(x, y); + + if (!CallbackBridge.isGrabbing()) { + /* + CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, isLeftMouseDown); + CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, 0, isRightMouseDown); + */ + CallbackBridge.sendScroll(x - scrollInitialX, y - scrollInitialY); + scrollInitialX = x; + scrollInitialY = y; + } + } + break; + } + } + +/* + int x = ((int) e.getX()) / scaleFactor; + int y = (minecraftGLView.getHeight() - ((int) e.getY())) / scaleFactor; + int hudKeyHandled = handleGuiBar(x, y, e); + if (!CallbackBridge.isGrabbing() && gestureDetector.onTouchEvent(e)) { + if (hudKeyHandled != -1) { + sendKeyPress(hudKeyHandled); + } else { + CallbackBridge.sendMouseEvent( + x, CallbackBridge.windowHeight - y, + rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT + ); + if (!rightOverride) { + CallbackBridge.mouseLeft = true; + } + } + } else { + switch (e.getActionMasked()) { + case MotionEvent.ACTION_DOWN: // 0 + case MotionEvent.ACTION_POINTER_DOWN: // 5 + isTouchInHotbar = hudKeyHandled != -1; + if (isTouchInHotbar) { + sendKeyPress(hudKeyHandled, 0, true); + hotbarX = x; + hotbarY = y; + + theHandler.sendEmptyMessageDelayed(MainActivity.MSG_DROP_ITEM_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); + } else { + CallbackBridge.sendCursorPos(x, CallbackBridge.windowHeight - y); + + // if (!rightOverride) + // CallbackBridge.mouseLeft = true; + + + + if (CallbackBridge.isGrabbing()) { + CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, true); + initialX = x; + initialY = y; + theHandler.sendEmptyMessageDelayed(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); + } + } + break; + case MotionEvent.ACTION_UP: // 1 + case MotionEvent.ACTION_CANCEL: // 3 + case MotionEvent.ACTION_POINTER_UP: // 6 + if (!isTouchInHotbar) { + CallbackBridge.sendCursorPos(x, CallbackBridge.windowHeight - y); + + // TODO uncomment after fix wrong trigger + // CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, (byte) 0, x, y); + if (!rightOverride) { + // CallbackBridge.mouseLeft = false; + } + } + + if (CallbackBridge.isGrabbing()) { + // System.out.println((String) ("[Math.abs(" + initialX + " - " + x + ") = " + Math.abs(initialX - x) + "] < " + fingerStillThreshold)); + // System.out.println((String) ("[Math.abs(" + initialY + " - " + y + ") = " + Math.abs(initialY - y) + "] < " + fingerStillThreshold)); + if (isTouchInHotbar && Math.abs(hotbarX - x) < fingerStillThreshold && Math.abs(hotbarY - y) < fingerStillThreshold) { + sendKeyPress(hudKeyHandled, 0, false); + } else if (!triggeredLeftMouseButton && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); + } + if (!isTouchInHotbar) { + if (triggeredLeftMouseButton) { + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, false); + } + triggeredLeftMouseButton = false; + theHandler.removeMessages(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK); + } else { + sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, false); + theHandler.removeMessages(MSG_DROP_ITEM_BUTTON_CHECK); + } + } + break; + + default: + if (!isTouchInHotbar) { + CallbackBridge.sendCursorPos(x, CallbackBridge.windowHeight - y); + } + break; + + } + } + */ + + debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); + + return true; + // return !CallbackBridge.isGrabbing(); + } + }; + + pointerCaptureListener = new OnTouchListener(){ + private int x, y; + private boolean debugErrored = false; + + private String getMoving(float pos, boolean xOrY) { + if (pos == 0) { + return "STOPPED"; + } else if (pos > 0) { + return xOrY ? "RIGHT" : "DOWN"; + } else { // if (pos3 < 0) { + return xOrY ? "LEFT" : "UP"; + } + } + + @Override + public boolean onTouch(View p1, MotionEvent e) + { + x += ((int) e.getX()) / scaleFactor; + y -= ((int) e.getY()) / scaleFactor; + + if (debugText.getVisibility() == View.VISIBLE && !debugErrored) { + StringBuilder builder = new StringBuilder(); + try { + builder.append("PointerCapture debug\n"); + builder.append("MotionEvent=" + e.getActionMasked() + "\n"); + builder.append("PressingBtn=" + MotionEvent.class.getDeclaredMethod("buttonStateToString").invoke(null, e.getButtonState()) + "\n\n"); + + builder.append("PointerX=" + e.getX() + "\n"); + builder.append("PointerY=" + e.getY() + "\n"); + builder.append("RawX=" + e.getRawX() + "\n"); + builder.append("RawY=" + e.getRawY() + "\n\n"); + + builder.append("XPos=" + x + "\n"); + builder.append("YPos=" + y + "\n\n"); + builder.append("MovingX=" + getMoving(e.getX(), true) + "\n"); + builder.append("MovingY=" + getMoving(e.getY(), false) + "\n"); + } catch (Throwable th) { + debugErrored = true; + builder.append("Error getting debug. The debug will be stopped!\n" + Log.getStackTraceString(th)); + } finally { + debugText.setText(builder.toString()); + builder.setLength(0); + } + } + + CallbackBridge.sendCursorPos(x, y); + + switch (e.getButtonState()) { + case MotionEvent.BUTTON_PRIMARY: CallbackBridge.mouseLeft = true; + break; + case MotionEvent.BUTTON_SECONDARY: CallbackBridge.mouseLeft = false; + break; + } + + switch (e.getActionMasked()) { + case MotionEvent.ACTION_DOWN: // 0 + case MotionEvent.ACTION_POINTER_DOWN: // 5 + CallbackBridge.sendPrepareGrabInitialPos(); + + CallbackBridge.sendMouseKeycode(CallbackBridge.mouseLeft ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, 0, true); + initialX = x; + initialY = y; + + sendMouseButton(CallbackBridge.mouseLeft ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); + + // theHandler.sendEmptyMessageDelayed(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); + break; + + case MotionEvent.ACTION_UP: // 1 + case MotionEvent.ACTION_CANCEL: // 3 + case MotionEvent.ACTION_POINTER_UP: // 6 + // CallbackBridge.sendCursorPos(x, y); + // CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, true); + CallbackBridge.putMouseEventWithCoords(CallbackBridge.mouseLeft /* rightOverride */ ? (byte) 0 : (byte) 1, (byte) 1, x, y); + /* + if (!triggeredLeftMouseButton && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); + } + if (triggeredLeftMouseButton) { + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, false); + } + */ + + sendMouseButton(CallbackBridge.mouseLeft ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); + + // triggeredLeftMouseButton = false; + // theHandler.removeMessages(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK); + break; + } + + debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); + + return true; + // If onClick fail with false, change back to true + } + }; + + if (isPointerCaptureSupported()) { + this.pointerSurface = new PointerOreoWrapper(minecraftGLView); + this.pointerSurface.setOnCapturedPointerListener(new PointerOreoWrapper.OnCapturedPointerListener(){ + @Override + public boolean onCapturedPointer(View view, MotionEvent event) { + return pointerCaptureListener.onTouch(view, event); + } + }); + } + + minecraftGLView.setOnHoverListener(new View.OnHoverListener(){ + @Override + public boolean onHover(View p1, MotionEvent p2) { + if (!CallbackBridge.isGrabbing() && mIsResuming) { + return glTouchListener.onTouch(p1, p2); + } + return true; + } + }); + minecraftGLView.setOnTouchListener(glTouchListener); + + minecraftGLView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener(){ + + private boolean isCalled = false; + @Override + public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { + CallbackBridge.windowWidth = width; + CallbackBridge.windowHeight = height; + calculateMcScale(); + + // Should we do that? + if (!isCalled) { + isCalled = true; + + JREUtils.setupBridgeWindow(new Surface(texture)); + + new Thread(new Runnable(){ + + @Override + public void run() { + try { + Thread.sleep(200); + runCraft(); + } catch (Throwable e) { + Tools.showError(BaseMainActivity.this, e, true); + } + } + }).start(); + } + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { + return true; + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { + CallbackBridge.windowWidth = width; + CallbackBridge.windowHeight = height; + CallbackBridge.sendUpdateWindowSize(width, height); + calculateMcScale(); + + // TODO: Implement this method for GLFW window size callback + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture texture) { + + } + }); + + OnGenericMotionListener gmlistener = new OnGenericMotionListener(){ + @Override + public boolean onGenericMotion(View v, MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_SCROLL: + CallbackBridge.sendScroll((double) event.getAxisValue(MotionEvent.AXIS_VSCROLL), (double) event.getAxisValue(MotionEvent.AXIS_HSCROLL)); + break; + } + return true; + } + }; + minecraftGLView.setOnGenericMotionListener(gmlistener); + touchPad.setOnGenericMotionListener(gmlistener); + } catch (Throwable e) { + e.printStackTrace(); + Tools.showError(this, e, true); + } + + // Mirror video of OpenGL view. + /* + new Thread(new Runnable(){ + + @Override + public void run() + { + try { + while (true) { + if (bit == null) continue; + runOnUiThread(new Runnable(){ + + @Override + public void run() + { + fillCanvasGL(); + mirrorView.setImageBitmap(bit); + } + }); + + // ~33fps render + Thread.sleep(30); + } + } catch (Throwable th) { + th.printStackTrace(); + } + } + }).start(); + */ + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) + { + AndroidLWJGLKeycode.execKey(this, event, keyCode, false); + return super.onKeyUp(keyCode, event); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + AndroidLWJGLKeycode.execKey(this, event, keyCode, true); + return super.onKeyDown(keyCode, event); + } + + //private Dialog menuDial; + + @Override + public void onResume() { + super.onResume(); + mIsResuming = true; + // if (minecraftGLView != null) minecraftGLView.requestRender(); + final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + final View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility(uiOptions); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + /* + if (hasFocus && minecraftGLView.getVisibility() == View.GONE) { + minecraftGLView.setVisibility(View.VISIBLE); + } + */ + } + + @Override + protected void onPause() + { + if (CallbackBridge.isGrabbing()){ + sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_ESCAPE); + } + mIsResuming = false; + super.onPause(); + } + + public boolean onTouch(View v, MotionEvent e) { + boolean isDown; + switch (e.getActionMasked()) { + case MotionEvent.ACTION_DOWN: // 0 + case MotionEvent.ACTION_POINTER_DOWN: // 5 + isDown = true; + break; + case MotionEvent.ACTION_UP: // 1 + case MotionEvent.ACTION_CANCEL: // 3 + case MotionEvent.ACTION_POINTER_UP: // 6 + isDown = false; + break; + default: + return false; + } + + switch (v.getId()) { + case R.id.control_up: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_W, 0, isDown); break; + case R.id.control_left: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_A, 0, isDown); break; + case R.id.control_down: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_S, 0, isDown); break; + case R.id.control_right: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_D, 0, isDown); break; + case R.id.control_jump: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_SPACE, 0, isDown); break; + case R.id.control_primary: sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown); break; + case R.id.control_secondary: + if (CallbackBridge.isGrabbing()) { + sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown); + } else { + /* + if (!isDown) { + CallbackBridge.putMouseEventWithCoords(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, CallbackBridge.mouseX, CallbackBridge.mouseY); + } + */ + + CallbackBridge.putMouseEventWithCoords(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown ? 1 : 0, CallbackBridge.mouseX, CallbackBridge.mouseY); + + setRightOverride(isDown); + } break; + case R.id.control_debug: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_F3, 0, isDown); break; + case R.id.control_shift: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, 0, isDown); break; + case R.id.control_inventory: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_E, 0, isDown); break; + case R.id.control_talk: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_T, 0, isDown); break; + case R.id.control_keyboard: showKeyboard(); break; + case R.id.control_thirdperson: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_F5, 0, isDown); break; + case R.id.control_zoom: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_C, 0, isDown); break; + case R.id.control_listplayers: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_TAB, 0, isDown); break; + } + + return false; + } + + public static void fullyExit() { + System.exit(0); + } + + public void forceUserHome(String s) throws Exception { + Properties props = System.getProperties(); + Class clazz = props.getClass(); + Field f = null; + while (clazz != null) { + try { + f = clazz.getDeclaredField("defaults"); + break; + } catch (Exception e) { + clazz = clazz.getSuperclass(); + } + } + if (f != null) { + f.setAccessible(true); + ((Properties) f.get(props)).put("user.home", s); + } + } + + private boolean isPointerCaptureSupported() { + return Build.VERSION.SDK_INT >= 26; + } + + // private FileObserver mLogObserver; + private void runCraft() throws Throwable { + /* Old logger + if (Tools.LAUNCH_TYPE != Tools.LTYPE_PROCESS) { + currLogFile = JREUtils.redirectStdio(true); + // DEPRECATED constructor (String) api 29 + mLogObserver = new FileObserver(currLogFile.getAbsolutePath(), FileObserver.MODIFY){ + @Override + public void onEvent(int event, String file) { + try { + if (event == FileObserver.MODIFY && currLogFile.length() > 0l) { + System.out.println(Tools.read(currLogFile.getAbsolutePath())); + Tools.write(currLogFile.getAbsolutePath(), ""); + } + } catch (Throwable th) { + Tools.showError(MainActivity.this, th); + mLogObserver.stopWatching(); + } + } + }; + mLogObserver.startWatching(); + } + */ + + appendlnToLog("--------- beggining with launcher debug"); + checkLWJGL3Installed(); + + Map jreReleaseList = readJREReleaseProperties(); + checkJavaArchitecture(jreReleaseList.get("OS_ARCH")); + checkJavaArgsIsLaunchable(jreReleaseList.get("JAVA_VERSION")); + // appendlnToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\""); + + JREUtils.redirectAndPrintJRELog(this, mProfile.getAccessToken()); + Tools.launchMinecraft(this, mProfile, mVersionInfo); + } + + private Map readJREReleaseProperties() throws IOException { + Map jreReleaseMap = new ArrayMap<>(); + BufferedReader jreReleaseReader = new BufferedReader(new FileReader(Tools.homeJreDir + "/release")); + String currLine; + while ((currLine = jreReleaseReader.readLine()) != null) { + if (!currLine.isEmpty() || currLine.contains("=")) { + String[] keyValue = currLine.split("="); + jreReleaseMap.put(keyValue[0], keyValue[1].replace("\"", "")); + } + } + jreReleaseReader.close(); + return jreReleaseMap; + } + + private void checkJavaArchitecture(String jreArch) throws Exception { + String[] argName = Tools.currentArch.split("/"); + appendlnToLog("Architecture: " + Tools.currentArch); + if (!(jreArch.contains(argName[0]) || jreArch.contains(argName[1]))) { + appendlnToLog("Architecture " + Tools.currentArch + " is incompatible with Java Runtime " + jreArch); + throw new RuntimeException(getString(R.string.mcn_check_fail_incompatiblearch, Tools.currentArch, jreArch)); + } + } + + private void checkJavaArgsIsLaunchable(String jreVersion) throws Throwable { + appendlnToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\""); + + if (jreVersion.equals("1.9.0")) return; + + /* + // Test java + ShellProcessOperation shell = new ShellProcessOperation(new ShellProcessOperation.OnPrintListener(){ + @Override + public void onPrintLine(String text){ + appendlnToLog("[JRETest] " + text); + } + }); + JREUtils.setJavaEnvironment(this, shell); + + List testArgs = new ArrayList(); + testArgs.add(Tools.homeJreDir + "/bin/java"); + Tools.getJavaArgs(this, testArgs); + testArgs.add("-version"); + + new File(Tools.homeJreDir + "/bin/java").setExecutable(true); + + // shell.writeToProcess("chmod 777 " + Tools.homeJreDir + "/bin/java"); + shell.writeToProcess("set -e"); + shell.writeToProcess(testArgs.toArray(new String[0])); + + int exitCode = shell.waitFor(); + appendlnToLog("Info: java test command exited with " + exitCode); + + if (exitCode != 0) { + appendlnToLog("Error: the test returned non-zero exit code."); + // throw new RuntimeException(getString(R.string.mcn_check_fail_java)); + } + */ + } + + private void checkLWJGL3Installed() { + File lwjgl3dir = new File(Tools.MAIN_PATH, "lwjgl3"); + if (!lwjgl3dir.exists() || lwjgl3dir.isFile() || lwjgl3dir.list().length == 0) { + appendlnToLog("Error: LWJGL3 was not installed!"); + throw new RuntimeException(getString(R.string.mcn_check_fail_lwjgl)); + } else { + appendlnToLog("Info: LWJGL3 directory: " + Arrays.toString(lwjgl3dir.list())); + } + } + + public void printStream(InputStream stream) { + try { + BufferedReader buffStream = new BufferedReader(new InputStreamReader(stream)); + String line = null; + while ((line = buffStream.readLine()) != null) { + appendlnToLog(line); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static String fromArray(List arr) { + String s = ""; + for (String exec : arr) { + s = s + " " + exec; + } + return s; + } + + private void toggleDebug() { + debugText.setVisibility(debugText.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); + } + + private void dialogSendCustomKey() { + AlertDialog.Builder dialog = new AlertDialog.Builder(this); + dialog.setTitle(R.string.control_customkey); + dialog.setItems(AndroidLWJGLKeycode.generateKeyName(), new DialogInterface.OnClickListener(){ + + @Override + public void onClick(DialogInterface dInterface, int position) { + AndroidLWJGLKeycode.execKeyIndex(BaseMainActivity.this, position); + } + }); + dialog.show(); + } + + private void openLogOutput() { + contentLog.setVisibility(View.VISIBLE); + mIsResuming = false; + } + + public void closeLogOutput(View view) { + contentLog.setVisibility(View.GONE); + mIsResuming = true; + } + /* + private void openCanvasOutput() { + WindowAnimation.fadeIn(contentCanvas, 500); + } + + public void closeCanvasOutput(View view) { + WindowAnimation.fadeOut(contentCanvas, 500); + } + */ + + @Override + public void appendToLog(final String text, boolean checkAllow) { + logStream.print(text); + if (checkAllow && !isLogAllow) return; + textLog.post(new Runnable(){ + @Override + public void run() { + textLog.append(text); + contentScroll.fullScroll(ScrollView.FOCUS_DOWN); + } + }); + } + + public String getMinecraftOption(String key) { + try { + String[] options = Tools.read(Tools.MAIN_PATH + "/options.txt").split("\n"); + for (String option : options) { + String[] optionKeyValue = option.split(":"); + if (optionKeyValue[0].equals(key)) { + return optionKeyValue[1]; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + public int mcscale(int input) { + return this.guiScale * input; + } + + /* + public int randomInRange(int min, int max) { + return min + (int)(Math.random() * (max - min + 1)); + } + */ + + public void toggleMenu(View v) { + drawerLayout.openDrawer(Gravity.RIGHT); + } + + public void placeMouseAdd(float x, float y) { + this.mousePointer.setTranslationX(mousePointer.getTranslationX() + x); + this.mousePointer.setTranslationY(mousePointer.getTranslationY() + y); + } + + public void placeMouseAt(float x, float y) { + this.mousePointer.setTranslationX(x); + this.mousePointer.setTranslationY(y); + } + + public void toggleMouse(View view) { + if (CallbackBridge.isGrabbing()) return; + + boolean isVis = touchPad.getVisibility() == View.VISIBLE; + touchPad.setVisibility(isVis ? View.GONE : View.VISIBLE); + ((Button) view).setText(isVis ? R.string.control_mouseoff: R.string.control_mouseon); + } + + public static void dialogForceClose(Context ctx) { + new AlertDialog.Builder(ctx) + .setMessage(R.string.mcn_exit_confirm) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){ + + @Override + public void onClick(DialogInterface p1, int p2) + { + try { + fullyExit(); + } catch (Throwable th) { + Log.w(Tools.APP_NAME, "Could not enable System.exit() method!", th); + } + + // If we are unable to enable exit, use method: kill myself. + // android.os.Process.killProcess(android.os.Process.myPid()); + + // Toast.makeText(MainActivity.this, "Could not exit. Please force close this app.", Toast.LENGTH_LONG).show(); + } + }) + .show(); + } + + protected Button findButton(int id) { + Button button = (Button) findViewById(id); + button.setWidth((int) Tools.dpToPx(this, Tools.pxToDp(this, button.getWidth()) * LauncherPreferences.PREF_BUTTONSIZE)); + button.setHeight((int) Tools.dpToPx(this, Tools.pxToDp(this, button.getHeight()) * LauncherPreferences.PREF_BUTTONSIZE)); + button.setOnTouchListener(this); + return button; + } + + @Override + public void onBackPressed() { + // Prevent back + // Catch back as Esc keycode at another place + } + + public void hideKeyboard() { + try { + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); + if (getCurrentFocus() != null && getCurrentFocus().getWindowToken() != null) { + ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this).getCurrentFocus().getWindowToken(), 0); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void showKeyboard() { + ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); + minecraftGLView.requestFocus(); + } + + private void setRightOverride(boolean val) { + this.rightOverride = val; + // this.secondaryButton.setBackgroundDrawable(this.rightOverride ? this.secondaryButtonColorBackground : this.secondaryButtonDefaultBackground); + } + + public void sendKeyPress(int keyCode, int modifiers, boolean status) { + sendKeyPress(keyCode, '\u0000', modifiers, status); + } + + public void sendKeyPress(int keyCode, char keyChar, int modifiers, boolean status) { + CallbackBridge.sendKeycode(keyCode, keyChar, modifiers, status); + } + + public void sendKeyPress(char keyChar) { + sendKeyPress(0, keyChar, 0, true); + sendKeyPress(0, keyChar, 0, false); + } + + public void sendKeyPress(int keyCode) { + sendKeyPress(keyCode, 0, true); + sendKeyPress(keyCode, 0, false); + } + + private boolean isLeftMouseDown, isRightMouseDown; + public void sendMouseButton(int button, boolean status) { + // TODO implement this method!!! + // CallbackBridge.setMouseButtonInGrabMode((byte) button, status ? (byte) 1 : (byte) 0); + // or + + isLeftMouseDown = button == LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT && status; + isRightMouseDown = button == LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT && status; + + CallbackBridge.sendMouseKeycode(button, 0, status); + } + + public void calculateMcScale() { + int scale = 1; + while (CallbackBridge.windowWidth / (scale + 1) >= 320 && CallbackBridge.windowHeight / (scale + 1) >= 240) { + scale++; + } + this.guiScale = scale; + } + + public int handleGuiBar(int x, int y) { + if (!CallbackBridge.isGrabbing()) return -1; + + int barheight = mcscale(20); + int barwidth = mcscale(180); + int barx = (CallbackBridge.windowWidth / 2) - (barwidth / 2); + int bary = CallbackBridge.windowHeight - barheight; + if (x < barx || x >= barx + barwidth || y < bary || y >= bary + barheight) { + return -1; + } + return hotbarKeys[((x - barx) / mcscale(180 / 9)) % 9]; + } +/* + public int handleGuiBar(int x, int y, MotionEvent e) { + if (!CallbackBridge.isGrabbing()) { + return -1; + } + + // int screenHeight = CallbackBridge.windowHeight; + int barheight = mcscale(20); + int barwidth = mcscale(180); + int barx = (CallbackBridge.windowWidth / 2) - (barwidth / 2); + if (x < barx || x >= barx + barwidth || y < 0 || y >= 0 + barheight) { + return -1; + } + return hotbarKeys[((x - barx) / mcscale(20)) % 9]; + } +*/ +} diff --git a/app/src/main/java/net/kdt/pojavlaunch/CustomControlsActivity.java b/app/src/main/java/net/kdt/pojavlaunch/CustomControlsActivity.java index 01793bdb3..2e75d41c0 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/CustomControlsActivity.java +++ b/app/src/main/java/net/kdt/pojavlaunch/CustomControlsActivity.java @@ -19,7 +19,7 @@ public class CustomControlsActivity extends AppCompatActivity { private DrawerLayout drawerLayout; private NavigationView navDrawer; - private ControlsLayout ctrlLayout; + private ControlLayout ctrlLayout; private CustomControls mCtrl; private SharedPreferences mPref; @@ -38,7 +38,7 @@ public class CustomControlsActivity extends AppCompatActivity gson = new GsonBuilder().setPrettyPrinting().create(); - ctrlLayout = (ControlsLayout) findViewById(R.id.customctrl_controllayout); + ctrlLayout = (ControlLayout) findViewById(R.id.customctrl_controllayout); // Menu drawerLayout = (DrawerLayout) findViewById(R.id.customctrl_drawerlayout); @@ -53,7 +53,7 @@ public class CustomControlsActivity extends AppCompatActivity actionLoad(); break; case R.id.menu_ctrl_add: - ctrlLayout.addControlButton(new ControlButton("New", LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, 100, 100)); + ctrlLayout.addControlButton(new ControlData("New", LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, 100, 100)); break; case R.id.menu_ctrl_selectdefault: dialogSelectDefaultCtrl(); diff --git a/app/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java b/app/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java index 8899a249e..f82adca85 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java +++ b/app/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java @@ -70,7 +70,7 @@ public class JavaGUILauncherActivity extends LoggableActivity { } public void forceClose(View v) { - MainActivity.dialogForceClose(this); + BaseMainActivity.dialogForceClose(this); } public void openLogOutput(View v) { diff --git a/app/src/main/java/net/kdt/pojavlaunch/MainActivity.java b/app/src/main/java/net/kdt/pojavlaunch/MainActivity.java index 0195e9aca..63f8e1030 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/MainActivity.java +++ b/app/src/main/java/net/kdt/pojavlaunch/MainActivity.java @@ -1,1295 +1,79 @@ package net.kdt.pojavlaunch; -import android.app.*; -import android.content.*; -import android.graphics.*; import android.os.*; -import android.support.design.widget.*; -import android.support.v4.widget.*; -import android.util.*; import android.view.*; import android.view.View.*; -import android.view.inputmethod.*; import android.widget.*; -import com.kdt.pointer.*; -import java.io.*; -import java.lang.reflect.*; -import java.util.*; import net.kdt.pojavlaunch.customcontrols.*; -import net.kdt.pojavlaunch.prefs.*; -import net.kdt.pojavlaunch.utils.*; -import org.lwjgl.glfw.*; -public class MainActivity extends LoggableActivity implements OnTouchListener, OnClickListener -{ - public static volatile ClipboardManager GLOBAL_CLIPBOARD; - - public static final String initText = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "; - volatile public static boolean isInputStackCall; - - private static 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}; - - private boolean rightOverride = false; - private int scaleFactor = 1; - private int fingerStillThreshold = 8; - private int initialX; - private int initialY; - private boolean mIsResuming = false; - private static final int MSG_LEFT_MOUSE_BUTTON_CHECK = 1028; - private static final int MSG_DROP_ITEM_BUTTON_CHECK = 1029; - private static boolean triggeredLeftMouseButton = false; - private Handler theHandler = new Handler() { - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_LEFT_MOUSE_BUTTON_CHECK: { - int x = CallbackBridge.mouseX; - int y = CallbackBridge.mouseY; - if (CallbackBridge.isGrabbing() && - Math.abs(initialX - x) < fingerStillThreshold && - Math.abs(initialY - y) < fingerStillThreshold) { - triggeredLeftMouseButton = true; - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); - } - } break; - case MSG_DROP_ITEM_BUTTON_CHECK: { - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, true); - } break; - } - } - }; - private MinecraftGLView minecraftGLView; - private int guiScale; - private DisplayMetrics displayMetrics; - public boolean hiddenTextIgnoreUpdate = true; - public String hiddenTextContents = initText; - private Button upButton, - downButton, leftButton, - rightButton, jumpButton, - primaryButton, secondaryButton, - debugButton, shiftButton, - keyboardButton, inventoryButton, - talkButton, thirdPersonButton, - zoomButton, listPlayersButton, +public class MainActivity extends BaseMainActivity implements OnClickListener { + private Button upButton, + downButton, leftButton, + rightButton, jumpButton, + primaryButton, secondaryButton, + debugButton, shiftButton, + keyboardButton, inventoryButton, + talkButton, thirdPersonButton, + zoomButton, listPlayersButton, toggleControlButton; - private LinearLayout touchPad; - private ImageView mousePointer; - //private EditText hiddenEditor; - // private ViewGroup overlayView; - private MCProfile.Builder mProfile; + + private Button[] controlButtons; - private DrawerLayout drawerLayout; - private NavigationView navDrawer; - - private LinearLayout contentLog; - private TextView textLog; - private ScrollView contentScroll; - private ToggleButton toggleLog; - private GestureDetector gestureDetector; - - private TextView debugText; - - private PointerOreoWrapper pointerSurface; - private View.OnTouchListener pointerCaptureListener; - - // private String mQueueText = new String(); - - private JMinecraftVersionList.Version mVersionInfo; - - private View.OnTouchListener glTouchListener; - - private Button[] controlButtons; - - private File logFile; - private PrintStream logStream; - - /* - private LinearLayout contentCanvas; - private AWTSurfaceView contentCanvasView; - */ - private boolean lastEnabled = false; - private boolean lastGrab = false; - private boolean isExited = false; - private boolean isLogAllow = false; - // private int navBarHeight = 40; - - // private static Collection rsaPkcs1List; - @Override - public void onCreate(Bundle savedInstanceState) - { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.main); - - try { - // FIXME: is it safe fot multi thread? - GLOBAL_CLIPBOARD = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); - - logFile = new File(Tools.MAIN_PATH, "latestlog.txt"); - logFile.delete(); - logFile.createNewFile(); - logStream = new PrintStream(logFile.getAbsolutePath()); - - Tools.setFullscreen(this); - - mProfile = PojavProfile.getCurrentProfileContent(this); - mVersionInfo = Tools.getVersionInfo(mProfile.getVersion()); - // Minecraft 1.12.x special case: use indirect char pipe - CallbackBridge.isMinecraft1p12 = mVersionInfo.assets.startsWith("1.12"); - - setTitle("Minecraft " + mProfile.getVersion()); - - // Minecraft 1.13+ - isInputStackCall = mVersionInfo.arguments != null; - - this.displayMetrics = Tools.getDisplayMetrics(this); - CallbackBridge.windowWidth = displayMetrics.widthPixels / scaleFactor; - CallbackBridge.windowHeight = displayMetrics.heightPixels / scaleFactor; - System.out.println("WidthHeight: " + CallbackBridge.windowWidth + ":" + CallbackBridge.windowHeight); - - gestureDetector = new GestureDetector(this, new SingleTapConfirm()); - - // Menu - drawerLayout = (DrawerLayout) findViewById(R.id.main_drawer_options); - - navDrawer = findViewById(R.id.main_navigation_view); - navDrawer.setNavigationItemSelectedListener( - new NavigationView.OnNavigationItemSelectedListener() { - @Override - public boolean onNavigationItemSelected(MenuItem menuItem) { - switch (menuItem.getItemId()) { - case R.id.nav_forceclose: dialogForceClose(MainActivity.this); - break; - case R.id.nav_viewlog: openLogOutput(); - break; - case R.id.nav_debug: toggleDebug(); - break; - case R.id.nav_customkey: dialogSendCustomKey(); - } - //Toast.makeText(MainActivity.this, menuItem.getTitle() + ":" + menuItem.getItemId(), Toast.LENGTH_SHORT).show(); - - drawerLayout.closeDrawers(); - return true; - } - }); - - this.upButton = findButton(R.id.control_up); - this.downButton = findButton(R.id.control_down); - this.leftButton = findButton(R.id.control_left); - this.rightButton = findButton(R.id.control_right); - this.jumpButton = findButton(R.id.control_jump); - this.primaryButton = findButton(R.id.control_primary); - this.secondaryButton = findButton(R.id.control_secondary); - this.debugButton = findButton(R.id.control_debug); - this.shiftButton = findButton(R.id.control_shift); - this.keyboardButton = findButton(R.id.control_keyboard); - this.inventoryButton = findButton(R.id.control_inventory); - this.talkButton = findButton(R.id.control_talk); - this.thirdPersonButton = findButton(R.id.control_thirdperson); - this.zoomButton = findButton(R.id.control_zoom); - this.listPlayersButton = findButton(R.id.control_listplayers); - this.toggleControlButton = findButton(R.id.control_togglecontrol); - this.controlButtons = new Button[]{ - upButton, downButton, leftButton, rightButton, - jumpButton, primaryButton, secondaryButton, - debugButton, shiftButton, keyboardButton, - inventoryButton, talkButton, thirdPersonButton, - listPlayersButton - }; - // this.overlayView = (ViewGroup) findViewById(R.id.main_control_overlay); - - //this.hiddenEditor = findViewById(R.id.hiddenTextbox); - - // Mouse pointer part - //this.mouseToggleButton = findButton(R.id.control_togglemouse); - this.touchPad = (LinearLayout) findViewById(R.id.main_touchpad); - this.mousePointer = (ImageView) findViewById(R.id.main_mouse_pointer); - - this.contentLog = (LinearLayout) findViewById(R.id.content_log_layout); - this.contentScroll = (ScrollView) findViewById(R.id.content_log_scroll); - this.textLog = (TextView) contentScroll.getChildAt(0); - this.toggleLog = (ToggleButton) findViewById(R.id.content_log_toggle_log); - this.toggleLog.setChecked(false); - // this.textLogBehindGL = (TextView) findViewById(R.id.main_log_behind_GL); - // this.textLogBehindGL.setTypeface(Typeface.MONOSPACE); - - this.textLog.setTypeface(Typeface.MONOSPACE); - this.toggleLog.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener(){ - - @Override - public void onCheckedChanged(CompoundButton button, boolean isChecked) - { - isLogAllow = isChecked; - appendToLog(""); - } - }); - - this.debugText = (TextView) findViewById(R.id.content_text_debug); - - this.toggleControlButton.setOnClickListener(this); - this.zoomButton.setVisibility(mVersionInfo.optifineLib == null ? View.GONE : View.VISIBLE); - - this.minecraftGLView = (MinecraftGLView) findViewById(R.id.main_game_render_view); - - ControlButton[] specialButtons = ControlButton.getSpecialButtons(); - specialButtons[0].specialButtonListener = new View.OnClickListener(){ - @Override - public void onClick(View view) { - showKeyboard(); - } - }; - specialButtons[1].specialButtonListener = new View.OnClickListener(){ - @Override - public void onClick(View view) { - MainActivity.this.onClick(toggleControlButton); - } - }; - - // toggleGui(null); - onClick(toggleControlButton); - this.drawerLayout.closeDrawers(); - - AndroidLWJGLKeycode.isBackspaceAfterChar = mVersionInfo.minimumLauncherVersion >= 18; - - placeMouseAt(CallbackBridge.windowWidth / 2, CallbackBridge.windowHeight / 2); - new Thread(new Runnable(){ - - private boolean isCapturing = false; - @Override - public void run() - { - while (!isExited) { - mousePointer.post(new Runnable(){ - - @Override - public void run() - { - if (lastGrab && !CallbackBridge.isGrabbing() && lastEnabled) { - touchPad.setVisibility(View.VISIBLE); - placeMouseAt(CallbackBridge.windowWidth / 2, CallbackBridge.windowHeight / 2); - } - - if (!CallbackBridge.isGrabbing()) { - lastEnabled = touchPad.getVisibility() == View.VISIBLE; - } else if (touchPad.getVisibility() != View.GONE) { - touchPad.setVisibility(View.GONE); - } - - if (isPointerCaptureSupported()) { - if (!CallbackBridge.isGrabbing() && isCapturing) { - pointerSurface.releaseCapture(); // minecraftGLView.releasePointerCapture(); - isCapturing = false; - } else if (CallbackBridge.isGrabbing() && !isCapturing) { - minecraftGLView.requestFocus(); - pointerSurface.requestCapture(); // minecraftGLView.requestPointerCapture(); - isCapturing = true; - } - } - - lastGrab = CallbackBridge.isGrabbing(); - } - }); - - try { - Thread.sleep(100); - } catch (Throwable th) {} - } - } - }).start(); - - 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(); - - float mouseX = mousePointer.getTranslationX(); - float mouseY = mousePointer.getTranslationY(); - - if (gestureDetector.onTouchEvent(event)) { - - CallbackBridge.sendCursorPos((int) mouseX, (int) mouseY); - CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT); - if (!rightOverride) { - CallbackBridge.mouseLeft = true; - } - - } else { - switch (action) { - case MotionEvent.ACTION_UP: // 1 - case MotionEvent.ACTION_CANCEL: // 3 - case MotionEvent.ACTION_POINTER_UP: // 6 - if (!rightOverride) { - CallbackBridge.mouseLeft = false; - } - break; - case MotionEvent.ACTION_MOVE: // 2 - mouseX = Math.max(0, Math.min(CallbackBridge.windowWidth, mouseX + x - prevX)); - mouseY = Math.max(0, Math.min(CallbackBridge.windowHeight, mouseY + y - prevY)); - placeMouseAt(mouseX, mouseY); - - CallbackBridge.sendCursorPos((int) mouseX, (int) mouseY); - /* - if (!CallbackBridge.isGrabbing()) { - CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, isLeftMouseDown); - CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, 0, isRightMouseDown); - } - */ - break; - } - } - prevX = x; - prevY = y; - - debugText.setText(CallbackBridge.DEBUG_STRING.toString()); - CallbackBridge.DEBUG_STRING.setLength(0); - - return true; - } - }); - - // System.loadLibrary("Regal"); - - minecraftGLView.setFocusable(true); - minecraftGLView.setFocusableInTouchMode(true); - // minecraftGLView.setEGLContextClientVersion(2); - - glTouchListener = new OnTouchListener(){ - private boolean isTouchInHotbar = false; - private int hotbarX, hotbarY; - private int scrollInitialX, scrollInitialY; - @Override - public boolean onTouch(View p1, MotionEvent e) - { - // System.out.println("Pre touch, isTouchInHotbar=" + Boolean.toString(isTouchInHotbar) + ", action=" + MotionEvent.actionToString(e.getActionMasked())); - int x = ((int) e.getX()) / scaleFactor; - int y = ((int) e.getY()) / scaleFactor; - int hudKeyHandled = handleGuiBar(x, y); - if (!CallbackBridge.isGrabbing() && gestureDetector.onTouchEvent(e)) { - if (hudKeyHandled != -1) { - sendKeyPress(hudKeyHandled); - } else { - CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, x, y); - if (!rightOverride) { - CallbackBridge.mouseLeft = true; - } - } - } else { - switch (e.getActionMasked()) { - case MotionEvent.ACTION_DOWN: // 0 - case MotionEvent.ACTION_POINTER_DOWN: // 5 - CallbackBridge.sendPrepareGrabInitialPos(); - - isTouchInHotbar = hudKeyHandled != -1; - if (isTouchInHotbar) { - sendKeyPress(hudKeyHandled, 0, true); - hotbarX = x; - hotbarY = y; - - theHandler.sendEmptyMessageDelayed(MainActivity.MSG_DROP_ITEM_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); - } else { - CallbackBridge.mouseX = x; - CallbackBridge.mouseY = y; - CallbackBridge.sendCursorPos(x, y); - if (!rightOverride) { - CallbackBridge.mouseLeft = true; - } - - if (CallbackBridge.isGrabbing()) { - // It cause hold left mouse while moving camera - // CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, (byte) 1, x, y); - initialX = x; - initialY = y; - theHandler.sendEmptyMessageDelayed(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); - } - - scrollInitialX = x; - scrollInitialY = y; - } - break; - - case MotionEvent.ACTION_UP: // 1 - case MotionEvent.ACTION_POINTER_UP: // 6 - case MotionEvent.ACTION_CANCEL: // 3 - if (!isTouchInHotbar) { - CallbackBridge.mouseX = x; - CallbackBridge.mouseY = y; - - // -TODO uncomment after fix wrong trigger - // CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, (byte) 0, x, y); - CallbackBridge.sendCursorPos(x, y); - if (!rightOverride) { - CallbackBridge.mouseLeft = false; - } - } - - if (CallbackBridge.isGrabbing()) { - // System.out.println((String) ("[Math.abs(" + initialX + " - " + x + ") = " + Math.abs(initialX - x) + "] < " + fingerStillThreshold)); - // System.out.println((String) ("[Math.abs(" + initialY + " - " + y + ") = " + Math.abs(initialY - y) + "] < " + fingerStillThreshold)); - if (isTouchInHotbar && Math.abs(hotbarX - x) < fingerStillThreshold && Math.abs(hotbarY - y) < fingerStillThreshold) { - sendKeyPress(hudKeyHandled, 0, false); - } else if (!triggeredLeftMouseButton && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); - } - if (!isTouchInHotbar) { - if (triggeredLeftMouseButton) { - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, false); - } - triggeredLeftMouseButton = false; - theHandler.removeMessages(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK); - } else { - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, false); - theHandler.removeMessages(MSG_DROP_ITEM_BUTTON_CHECK); - } - } - - break; -/* - case MotionEvent.ACTION_POINTER_DOWN: // 5 - CallbackBridge.sendScroll(x - scrollInitialX, y - scrollInitialY); - scrollInitialX = x; - scrollInitialY = y; - break; - - case MotionEvent.ACTION_POINTER_UP: // 6 - scrollInitialX = x; - scrollInitialY = y; - break; - */ - case MotionEvent.ACTION_MOVE: - if (!isTouchInHotbar) { - CallbackBridge.mouseX = x; - CallbackBridge.mouseY = y; - - CallbackBridge.sendCursorPos(x, y); - - if (!CallbackBridge.isGrabbing()) { - /* - CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, isLeftMouseDown); - CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, 0, isRightMouseDown); - */ - CallbackBridge.sendScroll(x - scrollInitialX, y - scrollInitialY); - scrollInitialX = x; - scrollInitialY = y; - } - } - break; - } - } - -/* - int x = ((int) e.getX()) / scaleFactor; - int y = (minecraftGLView.getHeight() - ((int) e.getY())) / scaleFactor; - int hudKeyHandled = handleGuiBar(x, y, e); - if (!CallbackBridge.isGrabbing() && gestureDetector.onTouchEvent(e)) { - if (hudKeyHandled != -1) { - sendKeyPress(hudKeyHandled); - } else { - CallbackBridge.sendMouseEvent( - x, CallbackBridge.windowHeight - y, - rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT - ); - if (!rightOverride) { - CallbackBridge.mouseLeft = true; - } - } - } else { - switch (e.getActionMasked()) { - case MotionEvent.ACTION_DOWN: // 0 - case MotionEvent.ACTION_POINTER_DOWN: // 5 - isTouchInHotbar = hudKeyHandled != -1; - if (isTouchInHotbar) { - sendKeyPress(hudKeyHandled, 0, true); - hotbarX = x; - hotbarY = y; - - theHandler.sendEmptyMessageDelayed(MainActivity.MSG_DROP_ITEM_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); - } else { - CallbackBridge.sendCursorPos(x, CallbackBridge.windowHeight - y); - - // if (!rightOverride) - // CallbackBridge.mouseLeft = true; - - - - if (CallbackBridge.isGrabbing()) { - CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, true); - initialX = x; - initialY = y; - theHandler.sendEmptyMessageDelayed(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); - } - } - break; - case MotionEvent.ACTION_UP: // 1 - case MotionEvent.ACTION_CANCEL: // 3 - case MotionEvent.ACTION_POINTER_UP: // 6 - if (!isTouchInHotbar) { - CallbackBridge.sendCursorPos(x, CallbackBridge.windowHeight - y); - - // TODO uncomment after fix wrong trigger - // CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, (byte) 0, x, y); - if (!rightOverride) { - // CallbackBridge.mouseLeft = false; - } - } - - if (CallbackBridge.isGrabbing()) { - // System.out.println((String) ("[Math.abs(" + initialX + " - " + x + ") = " + Math.abs(initialX - x) + "] < " + fingerStillThreshold)); - // System.out.println((String) ("[Math.abs(" + initialY + " - " + y + ") = " + Math.abs(initialY - y) + "] < " + fingerStillThreshold)); - if (isTouchInHotbar && Math.abs(hotbarX - x) < fingerStillThreshold && Math.abs(hotbarY - y) < fingerStillThreshold) { - sendKeyPress(hudKeyHandled, 0, false); - } else if (!triggeredLeftMouseButton && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); - } - if (!isTouchInHotbar) { - if (triggeredLeftMouseButton) { - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, false); - } - triggeredLeftMouseButton = false; - theHandler.removeMessages(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK); - } else { - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_Q, 0, false); - theHandler.removeMessages(MSG_DROP_ITEM_BUTTON_CHECK); - } - } - break; - - default: - if (!isTouchInHotbar) { - CallbackBridge.sendCursorPos(x, CallbackBridge.windowHeight - y); - } - break; - - } - } - */ - - debugText.setText(CallbackBridge.DEBUG_STRING.toString()); - CallbackBridge.DEBUG_STRING.setLength(0); - - return true; - // return !CallbackBridge.isGrabbing(); - } - }; - - pointerCaptureListener = new OnTouchListener(){ - private int x, y; - private boolean debugErrored = false; - - private String getMoving(float pos, boolean xOrY) { - if (pos == 0) { - return "STOPPED"; - } else if (pos > 0) { - return xOrY ? "RIGHT" : "DOWN"; - } else { // if (pos3 < 0) { - return xOrY ? "LEFT" : "UP"; - } - } - - @Override - public boolean onTouch(View p1, MotionEvent e) - { - x += ((int) e.getX()) / scaleFactor; - y -= ((int) e.getY()) / scaleFactor; - - if (debugText.getVisibility() == View.VISIBLE && !debugErrored) { - StringBuilder builder = new StringBuilder(); - try { - builder.append("PointerCapture debug\n"); - builder.append("MotionEvent=" + e.getActionMasked() + "\n"); - builder.append("PressingBtn=" + MotionEvent.class.getDeclaredMethod("buttonStateToString").invoke(null, e.getButtonState()) + "\n\n"); - - builder.append("PointerX=" + e.getX() + "\n"); - builder.append("PointerY=" + e.getY() + "\n"); - builder.append("RawX=" + e.getRawX() + "\n"); - builder.append("RawY=" + e.getRawY() + "\n\n"); - - builder.append("XPos=" + x + "\n"); - builder.append("YPos=" + y + "\n\n"); - builder.append("MovingX=" + getMoving(e.getX(), true) + "\n"); - builder.append("MovingY=" + getMoving(e.getY(), false) + "\n"); - } catch (Throwable th) { - debugErrored = true; - builder.append("Error getting debug. The debug will be stopped!\n" + Log.getStackTraceString(th)); - } finally { - debugText.setText(builder.toString()); - builder.setLength(0); - } - } - - CallbackBridge.sendCursorPos(x, y); - - switch (e.getButtonState()) { - case MotionEvent.BUTTON_PRIMARY: CallbackBridge.mouseLeft = true; - break; - case MotionEvent.BUTTON_SECONDARY: CallbackBridge.mouseLeft = false; - break; - } - - switch (e.getActionMasked()) { - case MotionEvent.ACTION_DOWN: // 0 - case MotionEvent.ACTION_POINTER_DOWN: // 5 - CallbackBridge.sendPrepareGrabInitialPos(); - - CallbackBridge.sendMouseKeycode(CallbackBridge.mouseLeft ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, 0, true); - initialX = x; - initialY = y; - - sendMouseButton(CallbackBridge.mouseLeft ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); - - // theHandler.sendEmptyMessageDelayed(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); - break; - - case MotionEvent.ACTION_UP: // 1 - case MotionEvent.ACTION_CANCEL: // 3 - case MotionEvent.ACTION_POINTER_UP: // 6 - // CallbackBridge.sendCursorPos(x, y); - // CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, 0, true); - CallbackBridge.putMouseEventWithCoords(CallbackBridge.mouseLeft /* rightOverride */ ? (byte) 0 : (byte) 1, (byte) 1, x, y); - /* - if (!triggeredLeftMouseButton && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, false); - } - if (triggeredLeftMouseButton) { - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, false); - } - */ - - sendMouseButton(CallbackBridge.mouseLeft ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, true); - - // triggeredLeftMouseButton = false; - // theHandler.removeMessages(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK); - break; - } - - debugText.setText(CallbackBridge.DEBUG_STRING.toString()); - CallbackBridge.DEBUG_STRING.setLength(0); - - return true; - // If onClick fail with false, change back to true - } - }; - - if (isPointerCaptureSupported()) { - this.pointerSurface = new PointerOreoWrapper(minecraftGLView); - this.pointerSurface.setOnCapturedPointerListener(new PointerOreoWrapper.OnCapturedPointerListener(){ - @Override - public boolean onCapturedPointer(View view, MotionEvent event) { - return pointerCaptureListener.onTouch(view, event); - } - }); - } - - minecraftGLView.setOnHoverListener(new View.OnHoverListener(){ - @Override - public boolean onHover(View p1, MotionEvent p2) { - if (!CallbackBridge.isGrabbing() && mIsResuming) { - return glTouchListener.onTouch(p1, p2); - } - return true; - } - }); - minecraftGLView.setOnTouchListener(glTouchListener); - - minecraftGLView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener(){ - - private boolean isCalled = false; - @Override - public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { - CallbackBridge.windowWidth = width; - CallbackBridge.windowHeight = height; - calculateMcScale(); - - // Should we do that? - if (!isCalled) { - isCalled = true; - - JREUtils.setupBridgeWindow(new Surface(texture)); - - new Thread(new Runnable(){ - - @Override - public void run() { - try { - Thread.sleep(200); - runCraft(); - } catch (Throwable e) { - Tools.showError(MainActivity.this, e, true); - } - } - }).start(); - } - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { - return true; - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { - CallbackBridge.windowWidth = width; - CallbackBridge.windowHeight = height; - CallbackBridge.sendUpdateWindowSize(width, height); - calculateMcScale(); - - // TODO: Implement this method for GLFW window size callback - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture texture) { - - } - }); - - OnGenericMotionListener gmlistener = new OnGenericMotionListener(){ - @Override - public boolean onGenericMotion(View v, MotionEvent event) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_SCROLL: - CallbackBridge.sendScroll((double) event.getAxisValue(MotionEvent.AXIS_VSCROLL), (double) event.getAxisValue(MotionEvent.AXIS_HSCROLL)); - break; - } - return true; - } - }; - minecraftGLView.setOnGenericMotionListener(gmlistener); - touchPad.setOnGenericMotionListener(gmlistener); - } catch (Throwable e) { - e.printStackTrace(); - Tools.showError(this, e, true); - } - - // Mirror video of OpenGL view. - /* - new Thread(new Runnable(){ - - @Override - public void run() - { - try { - while (true) { - if (bit == null) continue; - runOnUiThread(new Runnable(){ - - @Override - public void run() - { - fillCanvasGL(); - mirrorView.setImageBitmap(bit); - } - }); - - // ~33fps render - Thread.sleep(30); - } - } catch (Throwable th) { - th.printStackTrace(); - } - } - }).start(); - */ - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) - { - AndroidLWJGLKeycode.execKey(this, event, keyCode, false); - return super.onKeyUp(keyCode, event); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) - { - AndroidLWJGLKeycode.execKey(this, event, keyCode, true); - return super.onKeyDown(keyCode, event); - } - - //private Dialog menuDial; - - @Override - public void onResume() { - super.onResume(); - mIsResuming = true; - // if (minecraftGLView != null) minecraftGLView.requestRender(); - final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - final View decorView = getWindow().getDecorView(); - decorView.setSystemUiVisibility(uiOptions); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - /* - if (hasFocus && minecraftGLView.getVisibility() == View.GONE) { - minecraftGLView.setVisibility(View.VISIBLE); - } - */ - } - - @Override - protected void onPause() - { - if (CallbackBridge.isGrabbing()){ - sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_ESCAPE); - } - mIsResuming = false; - super.onPause(); - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.control_togglecontrol: { - /* - switch(overlayView.getVisibility()){ - case View.VISIBLE: overlayView.setVisibility(View.GONE); - break; - case View.GONE: overlayView.setVisibility(View.VISIBLE); - } - */ - - for (Button button : controlButtons) { - button.setVisibility(button.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); - } - - zoomButton.setVisibility((zoomButton.getVisibility() == View.GONE && mVersionInfo.optifineLib != null) ? View.VISIBLE : View.GONE); - } - } - } - - public boolean onTouch(View v, MotionEvent e) { - boolean isDown; - switch (e.getActionMasked()) { - case MotionEvent.ACTION_DOWN: // 0 - case MotionEvent.ACTION_POINTER_DOWN: // 5 - isDown = true; - break; - case MotionEvent.ACTION_UP: // 1 - case MotionEvent.ACTION_CANCEL: // 3 - case MotionEvent.ACTION_POINTER_UP: // 6 - isDown = false; - break; - default: - return false; - } - - switch (v.getId()) { - case R.id.control_up: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_W, 0, isDown); break; - case R.id.control_left: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_A, 0, isDown); break; - case R.id.control_down: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_S, 0, isDown); break; - case R.id.control_right: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_D, 0, isDown); break; - case R.id.control_jump: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_SPACE, 0, isDown); break; - case R.id.control_primary: sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown); break; - case R.id.control_secondary: - if (CallbackBridge.isGrabbing()) { - sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown); - } else { - /* - if (!isDown) { - CallbackBridge.putMouseEventWithCoords(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, CallbackBridge.mouseX, CallbackBridge.mouseY); - } - */ - - CallbackBridge.putMouseEventWithCoords(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown ? 1 : 0, CallbackBridge.mouseX, CallbackBridge.mouseY); - - setRightOverride(isDown); - } break; - case R.id.control_debug: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_F3, 0, isDown); break; - case R.id.control_shift: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, 0, isDown); break; - case R.id.control_inventory: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_E, 0, isDown); break; - case R.id.control_talk: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_T, 0, isDown); break; - case R.id.control_keyboard: showKeyboard(); break; - case R.id.control_thirdperson: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_F5, 0, isDown); break; - case R.id.control_zoom: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_C, 0, isDown); break; - case R.id.control_listplayers: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_TAB, 0, isDown); break; - } - - return false; + + this.upButton = findButton(R.id.control_up); + this.downButton = findButton(R.id.control_down); + this.leftButton = findButton(R.id.control_left); + this.rightButton = findButton(R.id.control_right); + this.jumpButton = findButton(R.id.control_jump); + this.primaryButton = findButton(R.id.control_primary); + this.secondaryButton = findButton(R.id.control_secondary); + this.debugButton = findButton(R.id.control_debug); + this.shiftButton = findButton(R.id.control_shift); + this.keyboardButton = findButton(R.id.control_keyboard); + this.inventoryButton = findButton(R.id.control_inventory); + this.talkButton = findButton(R.id.control_talk); + this.thirdPersonButton = findButton(R.id.control_thirdperson); + this.zoomButton = findButton(R.id.control_zoom); + this.listPlayersButton = findButton(R.id.control_listplayers); + this.toggleControlButton = findButton(R.id.control_togglecontrol); + this.controlButtons = new Button[]{ + upButton, downButton, leftButton, rightButton, + jumpButton, primaryButton, secondaryButton, + debugButton, shiftButton, keyboardButton, + inventoryButton, talkButton, thirdPersonButton, + listPlayersButton + }; + this.toggleControlButton.setOnClickListener(this); + this.zoomButton.setVisibility(mVersionInfo.optifineLib == null ? View.GONE : View.VISIBLE); + + ControlData[] specialButtons = ControlData.getSpecialButtons(); + specialButtons[1].specialButtonListener = this; + + // toggleGui(null); + onClick(toggleControlButton); } - public static void fullyExit() { - System.exit(0); - } - - public void forceUserHome(String s) throws Exception { - Properties props = System.getProperties(); - Class clazz = props.getClass(); - Field f = null; - while (clazz != null) { - try { - f = clazz.getDeclaredField("defaults"); - break; - } catch (Exception e) { - clazz = clazz.getSuperclass(); - } - } - if (f != null) { - f.setAccessible(true); - ((Properties) f.get(props)).put("user.home", s); - } - } - - private boolean isPointerCaptureSupported() { - return Build.VERSION.SDK_INT >= 26; - } - - // private FileObserver mLogObserver; - private void runCraft() throws Throwable { - /* Old logger - if (Tools.LAUNCH_TYPE != Tools.LTYPE_PROCESS) { - currLogFile = JREUtils.redirectStdio(true); - // DEPRECATED constructor (String) api 29 - mLogObserver = new FileObserver(currLogFile.getAbsolutePath(), FileObserver.MODIFY){ - @Override - public void onEvent(int event, String file) { - try { - if (event == FileObserver.MODIFY && currLogFile.length() > 0l) { - System.out.println(Tools.read(currLogFile.getAbsolutePath())); - Tools.write(currLogFile.getAbsolutePath(), ""); - } - } catch (Throwable th) { - Tools.showError(MainActivity.this, th); - mLogObserver.stopWatching(); - } - } - }; - mLogObserver.startWatching(); - } - */ - - appendlnToLog("--------- beggining with launcher debug"); - checkLWJGL3Installed(); - - Map jreReleaseList = readJREReleaseProperties(); - checkJavaArchitecture(jreReleaseList.get("OS_ARCH")); - checkJavaArgsIsLaunchable(jreReleaseList.get("JAVA_VERSION")); - // appendlnToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\""); - - JREUtils.redirectAndPrintJRELog(this, mProfile.getAccessToken()); - Tools.launchMinecraft(this, mProfile, mVersionInfo); - } - - private Map readJREReleaseProperties() throws IOException { - Map jreReleaseMap = new ArrayMap<>(); - BufferedReader jreReleaseReader = new BufferedReader(new FileReader(Tools.homeJreDir + "/release")); - String currLine; - while ((currLine = jreReleaseReader.readLine()) != null) { - if (!currLine.isEmpty() || currLine.contains("=")) { - String[] keyValue = currLine.split("="); - jreReleaseMap.put(keyValue[0], keyValue[1].replace("\"", "")); - } - } - jreReleaseReader.close(); - return jreReleaseMap; - } - - private void checkJavaArchitecture(String jreArch) throws Exception { - String[] argName = Tools.currentArch.split("/"); - appendlnToLog("Architecture: " + Tools.currentArch); - if (!(jreArch.contains(argName[0]) || jreArch.contains(argName[1]))) { - appendlnToLog("Architecture " + Tools.currentArch + " is incompatible with Java Runtime " + jreArch); - throw new RuntimeException(getString(R.string.mcn_check_fail_incompatiblearch, Tools.currentArch, jreArch)); - } - } - - private void checkJavaArgsIsLaunchable(String jreVersion) throws Throwable { - appendlnToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\""); - - if (jreVersion.equals("1.9.0")) return; - - /* - // Test java - ShellProcessOperation shell = new ShellProcessOperation(new ShellProcessOperation.OnPrintListener(){ - @Override - public void onPrintLine(String text){ - appendlnToLog("[JRETest] " + text); - } - }); - JREUtils.setJavaEnvironment(this, shell); - - List testArgs = new ArrayList(); - testArgs.add(Tools.homeJreDir + "/bin/java"); - Tools.getJavaArgs(this, testArgs); - testArgs.add("-version"); - - new File(Tools.homeJreDir + "/bin/java").setExecutable(true); - - // shell.writeToProcess("chmod 777 " + Tools.homeJreDir + "/bin/java"); - shell.writeToProcess("set -e"); - shell.writeToProcess(testArgs.toArray(new String[0])); - - int exitCode = shell.waitFor(); - appendlnToLog("Info: java test command exited with " + exitCode); - - if (exitCode != 0) { - appendlnToLog("Error: the test returned non-zero exit code."); - // throw new RuntimeException(getString(R.string.mcn_check_fail_java)); - } - */ - } - - private void checkLWJGL3Installed() { - File lwjgl3dir = new File(Tools.MAIN_PATH, "lwjgl3"); - if (!lwjgl3dir.exists() || lwjgl3dir.isFile() || lwjgl3dir.list().length == 0) { - appendlnToLog("Error: LWJGL3 was not installed!"); - throw new RuntimeException(getString(R.string.mcn_check_fail_lwjgl)); - } else { - appendlnToLog("Info: LWJGL3 directory: " + Arrays.toString(lwjgl3dir.list())); - } - } - - public void printStream(InputStream stream) { - try { - BufferedReader buffStream = new BufferedReader(new InputStreamReader(stream)); - String line = null; - while ((line = buffStream.readLine()) != null) { - appendlnToLog(line); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static String fromArray(List arr) { - String s = ""; - for (String exec : arr) { - s = s + " " + exec; - } - return s; - } - - private void toggleDebug() { - debugText.setVisibility(debugText.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); - } - - private void dialogSendCustomKey() { - AlertDialog.Builder dialog = new AlertDialog.Builder(this); - dialog.setTitle(R.string.control_customkey); - dialog.setItems(AndroidLWJGLKeycode.generateKeyName(), new DialogInterface.OnClickListener(){ - - @Override - public void onClick(DialogInterface dInterface, int position) { - AndroidLWJGLKeycode.execKeyIndex(MainActivity.this, position); - } - }); - dialog.show(); - } - - private void openLogOutput() { - contentLog.setVisibility(View.VISIBLE); - mIsResuming = false; - } - - public void closeLogOutput(View view) { - contentLog.setVisibility(View.GONE); - mIsResuming = true; - } - /* - private void openCanvasOutput() { - WindowAnimation.fadeIn(contentCanvas, 500); - } - - public void closeCanvasOutput(View view) { - WindowAnimation.fadeOut(contentCanvas, 500); - } - */ - @Override - public void appendToLog(final String text, boolean checkAllow) { - logStream.print(text); - if (checkAllow && !isLogAllow) return; - textLog.post(new Runnable(){ - @Override - public void run() { - textLog.append(text); - contentScroll.fullScroll(ScrollView.FOCUS_DOWN); - } - }); - } + public void onClick(View view) { + switch (view.getId()) { + case R.id.control_togglecontrol: { + /* + switch(overlayView.getVisibility()){ + case View.VISIBLE: overlayView.setVisibility(View.GONE); + break; + case View.GONE: overlayView.setVisibility(View.VISIBLE); + } + */ - public String getMinecraftOption(String key) { - try { - String[] options = Tools.read(Tools.MAIN_PATH + "/options.txt").split("\n"); - for (String option : options) { - String[] optionKeyValue = option.split(":"); - if (optionKeyValue[0].equals(key)) { - return optionKeyValue[1]; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return ""; - } + for (Button button : controlButtons) { + button.setVisibility(button.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); + } - public int mcscale(int input) { - return this.guiScale * input; - } - - /* - public int randomInRange(int min, int max) { - return min + (int)(Math.random() * (max - min + 1)); - } - */ - - public void toggleMenu(View v) { - drawerLayout.openDrawer(Gravity.RIGHT); - } - - public void placeMouseAdd(float x, float y) { - this.mousePointer.setTranslationX(mousePointer.getTranslationX() + x); - this.mousePointer.setTranslationY(mousePointer.getTranslationY() + y); - } - - public void placeMouseAt(float x, float y) { - this.mousePointer.setTranslationX(x); - this.mousePointer.setTranslationY(y); - } - - public void toggleMouse(View view) { - if (CallbackBridge.isGrabbing()) return; - - boolean isVis = touchPad.getVisibility() == View.VISIBLE; - touchPad.setVisibility(isVis ? View.GONE : View.VISIBLE); - ((Button) view).setText(isVis ? R.string.control_mouseoff: R.string.control_mouseon); - } - - public static void dialogForceClose(Context ctx) { - new AlertDialog.Builder(ctx) - .setMessage(R.string.mcn_exit_confirm) - .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){ - - @Override - public void onClick(DialogInterface p1, int p2) - { - try { - fullyExit(); - } catch (Throwable th) { - Log.w(Tools.APP_NAME, "Could not enable System.exit() method!", th); - } - - // If we are unable to enable exit, use method: kill myself. - // android.os.Process.killProcess(android.os.Process.myPid()); - - // Toast.makeText(MainActivity.this, "Could not exit. Please force close this app.", Toast.LENGTH_LONG).show(); - } - }) - .show(); - } - - private Button findButton(int id) { - Button button = (Button) findViewById(id); - button.setWidth((int) Tools.dpToPx(this, Tools.pxToDp(this, button.getWidth()) * LauncherPreferences.PREF_BUTTONSIZE)); - button.setHeight((int) Tools.dpToPx(this, Tools.pxToDp(this, button.getHeight()) * LauncherPreferences.PREF_BUTTONSIZE)); - button.setOnTouchListener(this); - return button; - } - - @Override - public void onBackPressed() { - // Prevent back - // Catch back as Esc keycode at another place - } - - public void hideKeyboard() { - try { - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); - if (getCurrentFocus() != null && getCurrentFocus().getWindowToken() != null) { - ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this).getCurrentFocus().getWindowToken(), 0); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void showKeyboard() { - ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); - minecraftGLView.requestFocus(); - } - - private void setRightOverride(boolean val) { - this.rightOverride = val; - // this.secondaryButton.setBackgroundDrawable(this.rightOverride ? this.secondaryButtonColorBackground : this.secondaryButtonDefaultBackground); - } - - public void sendKeyPress(int keyCode, int modifiers, boolean status) { - sendKeyPress(keyCode, '\u0000', modifiers, status); - } - - public void sendKeyPress(int keyCode, char keyChar, int modifiers, boolean status) { - CallbackBridge.sendKeycode(keyCode, keyChar, modifiers, status); - } - - public void sendKeyPress(char keyChar) { - sendKeyPress(0, keyChar, 0, true); - sendKeyPress(0, keyChar, 0, false); - } - - public void sendKeyPress(int keyCode) { - sendKeyPress(keyCode, 0, true); - sendKeyPress(keyCode, 0, false); - } - - private boolean isLeftMouseDown, isRightMouseDown; - public void sendMouseButton(int button, boolean status) { - // TODO implement this method!!! - // CallbackBridge.setMouseButtonInGrabMode((byte) button, status ? (byte) 1 : (byte) 0); - // or - - isLeftMouseDown = button == LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT && status; - isRightMouseDown = button == LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT && status; - - CallbackBridge.sendMouseKeycode(button, 0, status); - } - - public void calculateMcScale() { - int scale = 1; - while (CallbackBridge.windowWidth / (scale + 1) >= 320 && CallbackBridge.windowHeight / (scale + 1) >= 240) { - scale++; + zoomButton.setVisibility((zoomButton.getVisibility() == View.GONE && mVersionInfo.optifineLib != null) ? View.VISIBLE : View.GONE); + } } - this.guiScale = scale; } - - public int handleGuiBar(int x, int y) { - if (!CallbackBridge.isGrabbing()) return -1; - - int barheight = mcscale(20); - int barwidth = mcscale(180); - int barx = (CallbackBridge.windowWidth / 2) - (barwidth / 2); - int bary = CallbackBridge.windowHeight - barheight; - if (x < barx || x >= barx + barwidth || y < bary || y >= bary + barheight) { - return -1; - } - return hotbarKeys[((x - barx) / mcscale(180 / 9)) % 9]; - } -/* - public int handleGuiBar(int x, int y, MotionEvent e) { - if (!CallbackBridge.isGrabbing()) { - return -1; - } - - // int screenHeight = CallbackBridge.windowHeight; - int barheight = mcscale(20); - int barwidth = mcscale(180); - int barx = (CallbackBridge.windowWidth / 2) - (barwidth / 2); - if (x < barx || x >= barx + barwidth || y < 0 || y >= 0 + barheight) { - return -1; - } - return hotbarKeys[((x - barx) / mcscale(20)) % 9]; - } -*/ } diff --git a/app/src/main/java/net/kdt/pojavlaunch/PojavApplication.java b/app/src/main/java/net/kdt/pojavlaunch/PojavApplication.java index 7bc612472..393f29216 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/PojavApplication.java +++ b/app/src/main/java/net/kdt/pojavlaunch/PojavApplication.java @@ -47,7 +47,7 @@ public class PojavApplication extends Application FatalErrorActivity.showError(PojavApplication.this, crashFile.getAbsolutePath(), storagePermAllowed, th); // android.os.Process.killProcess(android.os.Process.myPid()); - MainActivity.fullyExit(); + BaseMainActivity.fullyExit(); } }); diff --git a/app/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java b/app/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java index 22c6d4633..cc11bb12d 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java +++ b/app/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java @@ -52,11 +52,11 @@ public class PojavLoginActivity extends AppCompatActivity super.onCreate(savedInstanceState); // false); Tools.updateWindowSize(this); - ControlButton.pixelOf2dp = (int) Tools.dpToPx(this, 2); - ControlButton.pixelOf30dp = (int) Tools.dpToPx(this, 30); - ControlButton.pixelOf50dp = (int) Tools.dpToPx(this, 50); - ControlButton.pixelOf80dp = (int) Tools.dpToPx(this, 80); - ControlButton[] specialButtons = ControlButton.getSpecialButtons(); + ControlData.pixelOf2dp = (int) Tools.dpToPx(this, 2); + ControlData.pixelOf30dp = (int) Tools.dpToPx(this, 30); + ControlData.pixelOf50dp = (int) Tools.dpToPx(this, 50); + ControlData.pixelOf80dp = (int) Tools.dpToPx(this, 80); + ControlData[] specialButtons = ControlData.getSpecialButtons(); specialButtons[0].name = getString(R.string.control_keyboard); specialButtons[1].name = getString(R.string.control_toggle); specialButtons[2].name = getString(R.string.control_primary); diff --git a/app/src/main/java/net/kdt/pojavlaunch/Tools.java b/app/src/main/java/net/kdt/pojavlaunch/Tools.java index 62e2bfe7d..183b3992f 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/app/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -98,7 +98,7 @@ public final class Tools @Override public void onClick(DialogInterface p1, int p2){ - MainActivity.fullyExit(); + BaseMainActivity.fullyExit(); } }); dialog.show(); @@ -202,7 +202,7 @@ public final class Tools } } - String[] argsFromJson = insertVariableArgument( + String[] argsFromJson = JSONUtils.insertJSONValueList( splitAndFilterEmpty( versionInfo.minecraftArguments == null ? fromStringArray(minecraftArgs.toArray(new String[0])): @@ -241,22 +241,6 @@ public final class Tools return strList.toArray(new String[0]); } - private static String[] insertVariableArgument(String[] args, Map keyValueMap) { - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - String argVar = null; - if (arg.startsWith("${") && arg.endsWith("}")) { - argVar = arg.substring(2, arg.length() - 1); - for (Map.Entry keyValue : keyValueMap.entrySet()) { - if (argVar.equals(keyValue.getKey())) { - args[i] = keyValue.getValue(); - } - } - } - } - return args; - } - public static String artifactToPath(String group, String artifact, String version) { return group.replaceAll("\\.", "/") + "/" + artifact + "/" + version + "/" + artifact + "-" + version + ".jar"; } @@ -432,8 +416,8 @@ public final class Tools public void onClick(DialogInterface p1, int p2) { if(exitIfOk) { - if (ctx instanceof MainActivity) { - MainActivity.fullyExit(); + if (ctx instanceof BaseMainActivity) { + BaseMainActivity.fullyExit(); } else if (ctx instanceof Activity) { ((Activity) ctx).finish(); } @@ -456,8 +440,8 @@ public final class Tools android.content.ClipboardManager mgr = (android.content.ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); mgr.setPrimaryClip(ClipData.newPlainText("error", Log.getStackTraceString(e))); if(exitIfOk) { - if (ctx instanceof MainActivity) { - MainActivity.fullyExit(); + if (ctx instanceof BaseMainActivity) { + BaseMainActivity.fullyExit(); } else { ((Activity) ctx).finish(); } diff --git a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlButton.java b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlButton.java index 5f5198214..c2a581741 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlButton.java +++ b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlButton.java @@ -1,99 +1,145 @@ package net.kdt.pojavlaunch.customcontrols; -import java.util.*; +import android.content.*; +import android.view.*; +import android.view.View.*; +import android.widget.*; import net.kdt.pojavlaunch.*; -import org.lwjgl.glfw.*; +import com.kdt.handleview.*; +import android.view.ViewGroup.*; -public class ControlButton implements Cloneable +public class ControlButton extends Button implements OnLongClickListener, OnTouchListener { - public static int pixelOf2dp; - public static int pixelOf30dp; - public static int pixelOf50dp; - public static int pixelOf80dp; - - public static final int SPECIALBTN_KEYBOARD = -1; - public static final int SPECIALBTN_TOGGLECTRL = -2; - public static final int SPECIALBTN_MOUSEPRI = -3; - public static final int SPECIALBTN_MOUSESEC = -4; - public static final int SPECIALBTN_VIRTUALMOUSE = -5; + private GestureDetector mGestureDetector; + private ControlData mProperties; + private SelectionEndHandleView mHandleView; - private static ControlButton[] SPECIAL_BUTTONS; - private static String[] SPECIAL_BUTTON_NAME_ARRAY; - - public static ControlButton[] getSpecialButtons(){ - if (SPECIAL_BUTTONS == null) { - SPECIAL_BUTTONS = new ControlButton[]{ - new ControlButton("Keyboard", SPECIALBTN_KEYBOARD, pixelOf2dp * 3 + pixelOf80dp * 2, pixelOf2dp, false), - new ControlButton("GUI", SPECIALBTN_TOGGLECTRL, pixelOf2dp, CallbackBridge.windowHeight - pixelOf50dp * 2 + pixelOf2dp * 4), - new ControlButton("PRI", SPECIALBTN_MOUSEPRI, pixelOf2dp, CallbackBridge.windowHeight - pixelOf50dp * 4 + pixelOf2dp * 2), - new ControlButton("SEC", SPECIALBTN_MOUSESEC, pixelOf2dp * 3 + pixelOf50dp * 2, CallbackBridge.windowHeight - pixelOf50dp * 4 + pixelOf2dp * 2), - new ControlButton("Mouse", SPECIALBTN_VIRTUALMOUSE, CallbackBridge.windowWidth - pixelOf80dp, pixelOf2dp, false) - }; - } - - return SPECIAL_BUTTONS; + private boolean mCanModify = false; + private boolean mCanTriggerLongClick = true; + + public ControlButton(Context ctx, ControlData properties) { + super(ctx); + + mGestureDetector = new GestureDetector(ctx, new SingleTapConfirm()); + + setBackgroundResource(R.drawable.control_button); + + setOnLongClickListener(this); + setOnTouchListener(this); + + setProperties(properties); + + mHandleView = new SelectionEndHandleView(this); + } + + public HandleView getHandleView() { + return mHandleView; } - public static String[] buildSpecialButtonArray() { - if (SPECIAL_BUTTON_NAME_ARRAY == null) { - List nameList = new ArrayList(); - for (ControlButton btn : getSpecialButtons()) { - nameList.add(btn.name); + public ControlData getProperties() { + return mProperties; + } + + public void setProperties(ControlData properties) { + setProperties(properties, true); + } + + public void setProperties(ControlData properties, boolean changePos) { + mProperties = properties; + // com.android.internal.R.string.delete + // android.R.string. + setText(properties.name); + if (changePos) { + setTranslationX(moveX = properties.x); + setTranslationY(moveY = properties.y); + } + + if (properties.specialButtonListener == null) { + // A non-special button or inside custom controls screen so skip listener + } else if (properties.specialButtonListener instanceof View.OnClickListener) { + setOnClickListener((View.OnClickListener) properties.specialButtonListener); + } else if (properties.specialButtonListener instanceof View.OnTouchListener) { + setOnTouchListener((View.OnTouchListener) properties.specialButtonListener); + } else { + throw new IllegalArgumentException("Field " + ControlData.class.getName() + ".specialButtonListener must be View.OnClickListener or View.OnTouchListener, but is " + properties.specialButtonListener.getClass().getName()); + } + + setLayoutParams(new FrameLayout.LayoutParams(properties.width, properties.height)); + } + + @Override + public void setLayoutParams(ViewGroup.LayoutParams params) + { + super.setLayoutParams(params); + + mProperties.width = params.width; + mProperties.height = params.height; + } + + @Override + public void setTranslationX(float x) + { + super.setTranslationX(x); + mProperties.x = x; + } + + @Override + public void setTranslationY(float y) { + super.setTranslationY(y); + mProperties.y = y; + } + + public void updateProperties() { + setProperties(mProperties); + } + + @Override + public boolean onLongClick(View p1) + { + if (!mCanTriggerLongClick) return false; + + if (mHandleView.isShowing()) { + mHandleView.hide(); + } else { + if (getParent() != null) { + ((ControlLayout) getParent()).hideAllHandleViews(); } - SPECIAL_BUTTON_NAME_ARRAY = nameList.toArray(new String[0]); + mHandleView.show(); } - - return SPECIAL_BUTTON_NAME_ARRAY; + return true; } - - public String name; - public float x; - public float y; - public int width = pixelOf50dp; - public int height = pixelOf50dp; - public int keycode; - public int keyindex; - public boolean hidden; - public boolean holdCtrl; - public boolean holdAlt; - public boolean holdShift; - public /* View.OnClickListener */ Object specialButtonListener; - // public boolean hold - - public ControlButton() { - this("", LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, 0, 0); + + private float moveX, moveY; + private float downX, downY; + @Override + public boolean onTouch(View view, MotionEvent event) { + if (!mCanModify) { + mCanTriggerLongClick = false; + + return false; + } + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mCanTriggerLongClick = true; + downX = event.getX(); + downY = event.getY(); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_MOVE: + mCanTriggerLongClick = false; + moveX += event.getX() - downX; + moveY += event.getY() - downY; + + setTranslationX(moveX); + setTranslationY(moveY); + break; + } + + return false; } - - public ControlButton(String name, int keycode) { - this(name, keycode, 0, 0); - } - - public ControlButton(String name, int keycode, float x, float y) { - this(name, keycode, x, y, pixelOf50dp, pixelOf50dp); - } - - public ControlButton(android.content.Context ctx, int resId, int keycode, float x, float y, boolean isSquare) { - this(ctx.getResources().getString(resId), keycode, x, y, isSquare); - } - - public ControlButton(String name, int keycode, float x, float y, boolean isSquare) { - this(name, keycode, x, y, isSquare ? pixelOf50dp : pixelOf80dp, isSquare ? pixelOf50dp : pixelOf30dp); - } - - public ControlButton(String name, int keycode, float x, float y, int width, int height) { - this.name = name; - this.keycode = keycode; - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - - public void execute(MainActivity act, boolean isDown) { - act.sendKeyPress(keycode, 0, isDown); - } - - public ControlButton clone() { - return new ControlButton(name, keycode, x, y, width, height); + + public void setModifiable(boolean z) { + mCanModify = z; } } diff --git a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlData.java b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlData.java new file mode 100644 index 000000000..455e63e49 --- /dev/null +++ b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlData.java @@ -0,0 +1,98 @@ +package net.kdt.pojavlaunch.customcontrols; + +import java.util.*; +import net.kdt.pojavlaunch.*; +import org.lwjgl.glfw.*; + +public class ControlData implements Cloneable +{ + public static int pixelOf2dp; + public static int pixelOf30dp; + public static int pixelOf50dp; + public static int pixelOf80dp; + + public static final int SPECIALBTN_KEYBOARD = -1; + public static final int SPECIALBTN_TOGGLECTRL = -2; + public static final int SPECIALBTN_MOUSEPRI = -3; + public static final int SPECIALBTN_MOUSESEC = -4; + public static final int SPECIALBTN_VIRTUALMOUSE = -5; + + private static ControlData[] SPECIAL_BUTTONS; + private static String[] SPECIAL_BUTTON_NAME_ARRAY; + + public static ControlData[] getSpecialButtons(){ + if (SPECIAL_BUTTONS == null) { + SPECIAL_BUTTONS = new ControlData[]{ + new DynamicControlData("Keyboard", SPECIALBTN_KEYBOARD, "${margin} * 3 + ${width} * 2", "${margin}", false), + new DynamicControlData("GUI", SPECIALBTN_TOGGLECTRL, "${margin}", "${screen_width} - ${width} * 2 + ${margin}"), + new DynamicControlData("PRI", SPECIALBTN_MOUSEPRI, "${margin}", "${screen_height} - ${height} * 4 + ${margin} * 2"), + new DynamicControlData("SEC", SPECIALBTN_MOUSESEC, "${margin} * 3 + ${width} * 2", "${screen_height} - ${height} * 4 + ${margin} * 2"), + new DynamicControlData("Mouse", SPECIALBTN_VIRTUALMOUSE, "${right}", "${margin}", false) + }; + } + + return SPECIAL_BUTTONS; + } + + public static String[] buildSpecialButtonArray() { + if (SPECIAL_BUTTON_NAME_ARRAY == null) { + List nameList = new ArrayList(); + for (ControlData btn : getSpecialButtons()) { + nameList.add(btn.name); + } + SPECIAL_BUTTON_NAME_ARRAY = nameList.toArray(new String[0]); + } + + return SPECIAL_BUTTON_NAME_ARRAY; + } + + public String name; + public float x; + public float y; + public int width = pixelOf50dp; + public int height = pixelOf50dp; + public int keycode; + public boolean hidden; + public boolean holdCtrl; + public boolean holdAlt; + public boolean holdShift; + public /* View.OnClickListener */ Object specialButtonListener; + // public boolean hold + + public ControlData() { + this("", LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, 0, 0); + } + + public ControlData(String name, int keycode) { + this(name, keycode, 0, 0); + } + + public ControlData(String name, int keycode, float x, float y) { + this(name, keycode, x, y, pixelOf50dp, pixelOf50dp); + } + + public ControlData(android.content.Context ctx, int resId, int keycode, float x, float y, boolean isSquare) { + this(ctx.getResources().getString(resId), keycode, x, y, isSquare); + } + + public ControlData(String name, int keycode, float x, float y, boolean isSquare) { + this(name, keycode, x, y, isSquare ? pixelOf50dp : pixelOf80dp, isSquare ? pixelOf50dp : pixelOf30dp); + } + + public ControlData(String name, int keycode, float x, float y, int width, int height) { + this.name = name; + this.keycode = keycode; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public void execute(BaseMainActivity act, boolean isDown) { + act.sendKeyPress(keycode, 0, isDown); + } + + public ControlData clone() { + return new ControlData(name, keycode, x, y, width, height); + } +} diff --git a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlsLayout.java b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlLayout.java similarity index 68% rename from app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlsLayout.java rename to app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlLayout.java index 653c8e3bc..701acf36f 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlsLayout.java +++ b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlLayout.java @@ -7,25 +7,25 @@ import com.google.gson.*; import net.kdt.pojavlaunch.*; import android.support.v7.app.*; -public class ControlsLayout extends FrameLayout +public class ControlLayout extends FrameLayout { private boolean mCanModify; private CustomControls mLayout; private CustomControlsActivity mActivity; private boolean mControlVisible = false; - public ControlsLayout(Context ctx) { + public ControlLayout(Context ctx) { super(ctx); } - public ControlsLayout(Context ctx, AttributeSet attrs) { + public ControlLayout(Context ctx, AttributeSet attrs) { super(ctx, attrs); } public void hideAllHandleViews() { for (int i = 0; i < getChildCount(); i++) { View view = getChildAt(i); - if (view instanceof ControlView) { - ((ControlView) view).getHandleView().hide(); + if (view instanceof ControlButton) { + ((ControlButton) view).getHandleView().hide(); } } } @@ -41,27 +41,27 @@ public class ControlsLayout extends FrameLayout public void loadLayout(CustomControls controlLayout) { mLayout = controlLayout; removeAllViews(); - for (ControlButton button : controlLayout.button) { + for (ControlData button : controlLayout.button) { addControlView(button); } setModified(false); } - public void addControlButton(ControlButton controlButton) { + public void addControlButton(ControlData controlButton) { mLayout.button.add(controlButton); addControlView(controlButton); } - private void addControlView(ControlButton controlButton) { - final ControlView view = new ControlView(getContext(), controlButton); + private void addControlView(ControlData controlButton) { + final ControlButton view = new ControlButton(getContext(), controlButton); view.setModifiable(mCanModify); addView(view); setModified(true); } - public void removeControlButton(ControlView controlButton) { + public void removeControlButton(ControlButton controlButton) { mLayout.button.remove(controlButton.getProperties()); controlButton.setVisibility(View.GONE); removeView(controlButton); @@ -84,8 +84,8 @@ public class ControlsLayout extends FrameLayout mControlVisible = !mControlVisible; for (int i = 0; i < getChildCount(); i++) { View view = getChildAt(i); - if (view instanceof ControlView && ((ControlView) view).getProperties().keycode != ControlButton.SPECIALBTN_TOGGLECTRL) { - ((ControlView) view).setVisibility(mControlVisible ? (((ControlView) view).getProperties().hidden ? View.INVISIBLE : View.VISIBLE) : View.GONE); + if (view instanceof ControlButton && ((ControlButton) view).getProperties().keycode != ControlData.SPECIALBTN_TOGGLECTRL) { + ((ControlButton) view).setVisibility(mControlVisible ? (((ControlButton) view).getProperties().hidden ? View.INVISIBLE : View.VISIBLE) : View.GONE); } } } @@ -94,8 +94,8 @@ public class ControlsLayout extends FrameLayout mCanModify = z; for (int i = 0; i < getChildCount(); i++) { View v = getChildAt(i); - if (v instanceof ControlView) { - ControlView cv = ((ControlView) v); + if (v instanceof ControlButton) { + ControlButton cv = ((ControlButton) v); cv.setModifiable(z); // cv.setVisibility(cv.getProperties().hidden ? View.INVISIBLE : View.VISIBLE); } diff --git a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlView.java b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlView.java deleted file mode 100644 index daff800f9..000000000 --- a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/ControlView.java +++ /dev/null @@ -1,145 +0,0 @@ -package net.kdt.pojavlaunch.customcontrols; - -import android.content.*; -import android.view.*; -import android.view.View.*; -import android.widget.*; -import net.kdt.pojavlaunch.*; -import com.kdt.handleview.*; -import android.view.ViewGroup.*; - -public class ControlView extends Button implements OnLongClickListener, OnTouchListener -{ - private GestureDetector mGestureDetector; - private ControlButton mProperties; - private SelectionEndHandleView mHandleView; - - private boolean mCanModify = false; - private boolean mCanTriggerLongClick = true; - - public ControlView(Context ctx, ControlButton properties) { - super(ctx); - - mGestureDetector = new GestureDetector(ctx, new SingleTapConfirm()); - - setBackgroundResource(R.drawable.control_button); - - setOnLongClickListener(this); - setOnTouchListener(this); - - setProperties(properties); - - mHandleView = new SelectionEndHandleView(this); - } - - public HandleView getHandleView() { - return mHandleView; - } - - public ControlButton getProperties() { - return mProperties; - } - - public void setProperties(ControlButton properties) { - setProperties(properties, true); - } - - public void setProperties(ControlButton properties, boolean changePos) { - mProperties = properties; - // com.android.internal.R.string.delete - // android.R.string. - setText(properties.name); - if (changePos) { - setTranslationX(moveX = properties.x); - setTranslationY(moveY = properties.y); - } - - if (properties.specialButtonListener == null) { - // A non-special button or inside custom controls screen so skip listener - } else if (properties.specialButtonListener instanceof View.OnClickListener) { - setOnClickListener((View.OnClickListener) properties.specialButtonListener); - } else if (properties.specialButtonListener instanceof View.OnTouchListener) { - setOnTouchListener((View.OnTouchListener) properties.specialButtonListener); - } else { - throw new IllegalArgumentException("Field " + ControlButton.class.getName() + ".specialButtonListener must be View.OnClickListener or View.OnTouchListener, but is " + properties.specialButtonListener.getClass().getName()); - } - - setLayoutParams(new FrameLayout.LayoutParams(properties.width, properties.height)); - } - - @Override - public void setLayoutParams(ViewGroup.LayoutParams params) - { - super.setLayoutParams(params); - - mProperties.width = params.width; - mProperties.height = params.height; - } - - @Override - public void setTranslationX(float x) - { - super.setTranslationX(x); - mProperties.x = x; - } - - @Override - public void setTranslationY(float y) { - super.setTranslationY(y); - mProperties.y = y; - } - - public void updateProperties() { - setProperties(mProperties); - } - - @Override - public boolean onLongClick(View p1) - { - if (!mCanTriggerLongClick) return false; - - if (mHandleView.isShowing()) { - mHandleView.hide(); - } else { - if (getParent() != null) { - ((ControlsLayout) getParent()).hideAllHandleViews(); - } - mHandleView.show(); - } - return true; - } - - private float moveX, moveY; - private float downX, downY; - @Override - public boolean onTouch(View view, MotionEvent event) { - if (!mCanModify) { - mCanTriggerLongClick = false; - - return false; - } - - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - mCanTriggerLongClick = true; - downX = event.getX(); - downY = event.getY(); - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_MOVE: - mCanTriggerLongClick = false; - moveX += event.getX() - downX; - moveY += event.getY() - downY; - - setTranslationX(moveX); - setTranslationY(moveY); - break; - } - - return false; - } - - public void setModifiable(boolean z) { - mCanModify = z; - } -} diff --git a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/CustomControls.java b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/CustomControls.java index 54d347205..4fe2652f3 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/CustomControls.java +++ b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/CustomControls.java @@ -7,37 +7,37 @@ import org.lwjgl.glfw.*; public class CustomControls { - public List button; + public List button; public CustomControls() { - this(new ArrayList()); + this(new ArrayList()); } - public CustomControls(List button) { + public CustomControls(List button) { this.button = button; } // Generate default control public CustomControls(Context ctx) { this(); - this.button.add(ControlButton.getSpecialButtons()[0].clone()); // Keyboard - this.button.add(ControlButton.getSpecialButtons()[1].clone()); // GUI - this.button.add(ControlButton.getSpecialButtons()[2].clone()); // Primary Mouse button - this.button.add(ControlButton.getSpecialButtons()[3].clone()); // Secondary Mouse button - this.button.add(ControlButton.getSpecialButtons()[4].clone()); // Virtual mouse toggle + this.button.add(ControlData.getSpecialButtons()[0].clone()); // Keyboard + this.button.add(ControlData.getSpecialButtons()[1].clone()); // GUI + this.button.add(ControlData.getSpecialButtons()[2].clone()); // Primary Mouse button + this.button.add(ControlData.getSpecialButtons()[3].clone()); // Secondary Mouse button + this.button.add(ControlData.getSpecialButtons()[4].clone()); // Virtual mouse toggle - this.button.add(new ControlButton(ctx, R.string.control_debug, LWJGLGLFWKeycode.GLFW_KEY_F3, ControlButton.pixelOf2dp, ControlButton.pixelOf2dp, false)); - this.button.add(new ControlButton(ctx, R.string.control_chat, LWJGLGLFWKeycode.GLFW_KEY_T, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf80dp, ControlButton.pixelOf2dp, false)); - this.button.add(new ControlButton(ctx, R.string.control_listplayers, LWJGLGLFWKeycode.GLFW_KEY_TAB, ControlButton.pixelOf2dp * 4 + ControlButton.pixelOf80dp * 3, ControlButton.pixelOf2dp, false)); - this.button.add(new ControlButton(ctx, R.string.control_thirdperson, LWJGLGLFWKeycode.GLFW_KEY_F5, ControlButton.pixelOf2dp, ControlButton.pixelOf30dp + ControlButton.pixelOf2dp, false)); + this.button.add(new DynamicControlData(ctx, R.string.control_debug, LWJGLGLFWKeycode.GLFW_KEY_F3, "${margin}", "${margin}", false)); + this.button.add(new DynamicControlData(ctx, R.string.control_chat, LWJGLGLFWKeycode.GLFW_KEY_T, "${margin} * 2 + ${width}", "${margin}", false)); + this.button.add(new DynamicControlData(ctx, R.string.control_listplayers, LWJGLGLFWKeycode.GLFW_KEY_TAB, "${margin} * 4 + ${width} * 3", "${margin}", false)); + this.button.add(new DynamicControlData(ctx, R.string.control_thirdperson, LWJGLGLFWKeycode.GLFW_KEY_F5, "${margin}", "${height} + ${margin}", false)); - this.button.add(new ControlButton(ctx, R.string.control_up, LWJGLGLFWKeycode.GLFW_KEY_W, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 3 - ControlButton.pixelOf50dp * 3, true)); - this.button.add(new ControlButton(ctx, R.string.control_left, LWJGLGLFWKeycode.GLFW_KEY_A, ControlButton.pixelOf2dp, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); - this.button.add(new ControlButton(ctx, R.string.control_down, LWJGLGLFWKeycode.GLFW_KEY_S, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, CallbackBridge.windowHeight - ControlButton.pixelOf2dp - ControlButton.pixelOf50dp, true)); - this.button.add(new ControlButton(ctx, R.string.control_right, LWJGLGLFWKeycode.GLFW_KEY_D, ControlButton.pixelOf2dp * 3 + ControlButton.pixelOf50dp * 2, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); + this.button.add(new DynamicControlData(ctx, R.string.control_up, LWJGLGLFWKeycode.GLFW_KEY_W, "${margin} * 2 + ${width}", "${screen_height} - ${margin} * 3 - ${height} * 3", true)); + this.button.add(new DynamicControlData(ctx, R.string.control_left, LWJGLGLFWKeycode.GLFW_KEY_A, "${margin}", "${screen_height} - ${margin} * 2 - ${height} * 2", true)); + this.button.add(new DynamicControlData(ctx, R.string.control_down, LWJGLGLFWKeycode.GLFW_KEY_S, "${margin} * 2 + ${width}", "${screen_height} - ${margin} - ${width}", true)); + this.button.add(new DynamicControlData(ctx, R.string.control_right, LWJGLGLFWKeycode.GLFW_KEY_D, "${margin} * 3 + ${width} * 2", "${screen_height} - ${margin} * 2 - ${width} * 2", true)); - this.button.add(new ControlButton(ctx, R.string.control_inventory, LWJGLGLFWKeycode.GLFW_KEY_E, ControlButton.pixelOf2dp * 3 + ControlButton.pixelOf50dp * 2, CallbackBridge.windowHeight - ControlButton.pixelOf2dp - ControlButton.pixelOf50dp, true)); - this.button.add(new ControlButton(ctx, R.string.control_shift, LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); - this.button.add(new ControlButton(ctx, R.string.control_jump, LWJGLGLFWKeycode.GLFW_KEY_SPACE, CallbackBridge.windowWidth - ControlButton.pixelOf2dp * 3 - ControlButton.pixelOf50dp * 2, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); + this.button.add(new DynamicControlData(ctx, R.string.control_inventory, LWJGLGLFWKeycode.GLFW_KEY_E, "${margin} * 3 + ${width} * 2", "${screen_height} - ${margin} - ${width}", true)); + this.button.add(new DynamicControlData(ctx, R.string.control_shift, LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, "${margin} * 2 + ${width}", "${screen_height} - ${margin} * 2 - ${width} * 2", true)); + this.button.add(new DynamicControlData(ctx, R.string.control_jump, LWJGLGLFWKeycode.GLFW_KEY_SPACE, "${screen_width} - ${margin} * 3 - ${width} * 2", "${screen_height} - ${margin} * 2 - ${width} * 2", true)); } diff --git a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/DynamicControlButton.java b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/DynamicControlButton.java deleted file mode 100644 index b6ce95fd7..000000000 --- a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/DynamicControlButton.java +++ /dev/null @@ -1,6 +0,0 @@ -package net.kdt.pojavlaunch.customcontrols; - -public class DynamicControlButton extends ControlButton -{ - // TODO for ${value} -} diff --git a/app/src/main/java/net/kdt/pojavlaunch/customcontrols/DynamicControlData.java b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/DynamicControlData.java new file mode 100644 index 000000000..f552b0432 --- /dev/null +++ b/app/src/main/java/net/kdt/pojavlaunch/customcontrols/DynamicControlData.java @@ -0,0 +1,77 @@ +package net.kdt.pojavlaunch.customcontrols; + +import android.util.*; +import java.util.*; +import net.kdt.pojavlaunch.*; +import net.kdt.pojavlaunch.utils.*; +import net.objecthunter.exp4j.*; +import org.lwjgl.glfw.*; + +public class DynamicControlData extends ControlData { + /** + * The DynamicControlData is a ControlData that uses dynamic + * X and Y position, unlike the original one which uses fixed + * position, so it does not provide autoscale when a control + * is made on a small device, then import the control to a + * bigger device or vice versa. + */ + + private String dynamicX, dynamicY; + + public DynamicControlData() { + this("", LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN); + } + + public DynamicControlData(String name, int keycode) { + this(name, keycode, "0", "0"); + } + + public DynamicControlData(String name, int keycode, String dynamicX, String dynamicY) { + this(name, keycode, dynamicX, dynamicY, pixelOf50dp, pixelOf50dp); + } + + public DynamicControlData(android.content.Context ctx, int resId, int keycode, String dynamicX, String dynamicY, boolean isSquare) { + this(ctx.getResources().getString(resId), keycode, dynamicX, dynamicY, isSquare); + } + + public DynamicControlData(String name, int keycode, String dynamicX, String dynamicY, boolean isSquare) { + this(name, keycode, dynamicX, dynamicY, isSquare ? pixelOf50dp : pixelOf80dp, isSquare ? pixelOf50dp : pixelOf30dp); + } + + public DynamicControlData(String name, int keycode, String dynamicX, String dynamicY, int width, int height) { + super(name, keycode, 0, 0, width, height); + this.dynamicX = dynamicX; + this.dynamicY = dynamicY; + update(); + } + + public void update() { + // Values in the map below may be always changed + Map keyValueMap = new ArrayMap<>(); + keyValueMap.put("top", "0"); + keyValueMap.put("left", "0"); + keyValueMap.put("right", Integer.toString(CallbackBridge.windowWidth - width)); + keyValueMap.put("bottom", Integer.toString(CallbackBridge.windowHeight - height)); + keyValueMap.put("width", Integer.toString(width)); + keyValueMap.put("height", Integer.toString(height)); + keyValueMap.put("screen_width", Integer.toString(CallbackBridge.windowWidth)); + keyValueMap.put("screen_height", Integer.toString(CallbackBridge.windowHeight)); + keyValueMap.put("margin", Integer.toString(pixelOf2dp)); + + // Insert JSON values to variables + String insertedX = JSONUtils.insertSingleJSONValue(dynamicX, keyValueMap); + String insertedY = JSONUtils.insertSingleJSONValue(dynamicY, keyValueMap); + + // Calculate and save, because the dynamic position contains some math equations + x = calculate(insertedX); + y = calculate(insertedY); + } + + private static int calculate(String math) { + // try { + return (int) new ExpressionBuilder(math).build().evaluate(); + /* } catch (e) { + + } */ + } +} diff --git a/app/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java b/app/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java index 5a79fc282..863a1a4ef 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java +++ b/app/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloaderTask.java @@ -229,7 +229,7 @@ public class MinecraftDownloaderTask extends AsyncTask keyValueMap) { + for (int i = 0; i < args.length; i++) { + args[i] = insertSingleJSONValue(args[i], keyValueMap); + } + return args; + } + + public static String insertSingleJSONValue(String value, Map keyValueMap) { + String valueInserted = value; + for (Map.Entry keyValue : keyValueMap.entrySet()) { + valueInserted = valueInserted.replace("${" + keyValue.getKey() + "}", keyValue.getValue()); + } + return valueInserted; + } +} diff --git a/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java index 9e1659665..aa2ea8617 100644 --- a/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java +++ b/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java @@ -32,7 +32,7 @@ public class CallbackBridge { private static boolean threadAttached; public static void sendCursorPos(int x, int y) { if (!threadAttached) { - threadAttached = CallbackBridge.nativeAttachThreadToOther(true, isMinecraft1p12, MainActivity.isInputStackCall); + threadAttached = CallbackBridge.nativeAttachThreadToOther(true, isMinecraft1p12, BaseMainActivity.isInputStackCall); } DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n"); @@ -85,12 +85,12 @@ public class CallbackBridge { public static String accessAndroidClipboard(int type, String copy) { switch (type) { case CLIPBOARD_COPY: - MainActivity.GLOBAL_CLIPBOARD.setPrimaryClip(ClipData.newPlainText("Copy", copy)); + BaseMainActivity.GLOBAL_CLIPBOARD.setPrimaryClip(ClipData.newPlainText("Copy", copy)); return null; case CLIPBOARD_PASTE: - if (MainActivity.GLOBAL_CLIPBOARD.hasPrimaryClip() && MainActivity.GLOBAL_CLIPBOARD.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { - return MainActivity.GLOBAL_CLIPBOARD.getPrimaryClip().getItemAt(0).getText().toString(); + if (BaseMainActivity.GLOBAL_CLIPBOARD.hasPrimaryClip() && BaseMainActivity.GLOBAL_CLIPBOARD.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { + return BaseMainActivity.GLOBAL_CLIPBOARD.getPrimaryClip().getItemAt(0).getText().toString(); } else { return ""; }