mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-08-04 08:06:55 -04:00
Merge branch 'v3_openjdk' into feat/quick_settings
This commit is contained in:
commit
eb6b23c76e
@ -5,7 +5,7 @@
|
|||||||
[](https://github.com/PojavLauncherTeam/PojavLauncher/actions)
|
[](https://github.com/PojavLauncherTeam/PojavLauncher/actions)
|
||||||
[](https://github.com/PojavLauncherTeam/PojavLauncher/actions)
|
[](https://github.com/PojavLauncherTeam/PojavLauncher/actions)
|
||||||
[](https://crowdin.com/project/pojavlauncher)
|
[](https://crowdin.com/project/pojavlauncher)
|
||||||
[](https://discord.com/invite/pojavlauncher-724163890803638273)
|
[](https://discord.com/invite/aenk3EUvER)
|
||||||
[](https://twitter.com/PLaunchTeam)
|
[](https://twitter.com/PLaunchTeam)
|
||||||
|
|
||||||
* From [Boardwalk](https://github.com/zhuowei/Boardwalk)'s ashes here comes PojavLauncher!
|
* From [Boardwalk](https://github.com/zhuowei/Boardwalk)'s ashes here comes PojavLauncher!
|
||||||
|
@ -442,38 +442,20 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
|
|||||||
if(touchCharInput != null) touchCharInput.switchKeyboardState();
|
if(touchCharInput != null) touchCharInput.switchKeyboardState();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setUri(Context context, String input, Intent intent) {
|
|
||||||
if(input.startsWith("file:")) {
|
|
||||||
int truncLength = 5;
|
|
||||||
if(input.startsWith("file://")) truncLength = 7;
|
|
||||||
input = input.substring(truncLength);
|
|
||||||
Log.i("MainActivity", input);
|
|
||||||
boolean isDirectory = new File(input).isDirectory();
|
|
||||||
if(isDirectory) {
|
|
||||||
intent.setType(DocumentsContract.Document.MIME_TYPE_DIR);
|
|
||||||
}else{
|
|
||||||
String type = null;
|
|
||||||
String extension = MimeTypeMap.getFileExtensionFromUrl(input);
|
|
||||||
if(extension != null) type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
|
||||||
if(type == null) type = "*/*";
|
|
||||||
intent.setType(type);
|
|
||||||
}
|
|
||||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
intent.setData(DocumentsContract.buildDocumentUri(
|
|
||||||
context.getString(R.string.storageProviderAuthorities), input
|
|
||||||
));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
intent.setDataAndType(Uri.parse(input), "*/*");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void openLink(String link) {
|
public static void openLink(String link) {
|
||||||
Context ctx = touchpad.getContext(); // no more better way to obtain a context statically
|
Context ctx = touchpad.getContext(); // no more better way to obtain a context statically
|
||||||
((Activity)ctx).runOnUiThread(() -> {
|
((Activity)ctx).runOnUiThread(() -> {
|
||||||
try {
|
try {
|
||||||
|
if(link.startsWith("file:")) {
|
||||||
|
int truncLength = 5;
|
||||||
|
if(link.startsWith("file://")) truncLength = 7;
|
||||||
|
String path = link.substring(truncLength);
|
||||||
|
Tools.openPath(ctx, new File(path), false);
|
||||||
|
}else {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
setUri(ctx, link, intent);
|
intent.setDataAndType(Uri.parse(link), "*/*");
|
||||||
ctx.startActivity(intent);
|
ctx.startActivity(intent);
|
||||||
|
}
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
Tools.showError(ctx, th);
|
Tools.showError(ctx, th);
|
||||||
}
|
}
|
||||||
@ -484,9 +466,7 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
|
|||||||
Context ctx = touchpad.getContext(); // no more better way to obtain a context statically
|
Context ctx = touchpad.getContext(); // no more better way to obtain a context statically
|
||||||
((Activity)ctx).runOnUiThread(() -> {
|
((Activity)ctx).runOnUiThread(() -> {
|
||||||
try {
|
try {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Tools.openPath(ctx, new File(path), false);
|
||||||
intent.setDataAndType(DocumentsContract.buildDocumentUri(ctx.getString(R.string.storageProviderAuthorities), path), "*/*");
|
|
||||||
ctx.startActivity(intent);
|
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
Tools.showError(ctx, th);
|
Tools.showError(ctx, th);
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ import org.apache.commons.codec.binary.Hex;
|
|||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.lwjgl.glfw.CallbackBridge;
|
import org.lwjgl.glfw.CallbackBridge;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -88,6 +89,7 @@ import java.io.PrintWriter;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.URLConnection;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -1192,17 +1194,55 @@ public final class Tools {
|
|||||||
|
|
||||||
/** Triggers the share intent chooser, with the latestlog file attached to it */
|
/** Triggers the share intent chooser, with the latestlog file attached to it */
|
||||||
public static void shareLog(Context context){
|
public static void shareLog(Context context){
|
||||||
Uri contentUri = DocumentsContract.buildDocumentUri(context.getString(R.string.storageProviderAuthorities), Tools.DIR_GAME_HOME + "/latestlog.txt");
|
openPath(context, new File(Tools.DIR_GAME_HOME, "latestlog.txt"), true);
|
||||||
|
}
|
||||||
|
|
||||||
Intent shareIntent = new Intent();
|
/**
|
||||||
shareIntent.setAction(Intent.ACTION_SEND);
|
* Determine the MIME type of a File.
|
||||||
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
|
* @param file The file to determine the type of
|
||||||
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
* @return the type, or the default value *slash* if cannot be determined
|
||||||
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
*/
|
||||||
shareIntent.setType("text/plain");
|
public static String getMimeType(File file) {
|
||||||
|
if(file.isDirectory()) return DocumentsContract.Document.MIME_TYPE_DIR;
|
||||||
|
String mimeType = null;
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(file)){
|
||||||
|
// Theoretically we don't even need the buffer since we don't care about the
|
||||||
|
// contents of the file after the guess, but mark-supported streams
|
||||||
|
// are a requirement of URLConnection.guessContentTypeFromStream()
|
||||||
|
try(BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream)) {
|
||||||
|
mimeType = URLConnection.guessContentTypeFromStream(bufferedInputStream);
|
||||||
|
}
|
||||||
|
}catch (IOException e) {
|
||||||
|
Log.w("FileMimeType", "Failed to determine MIME type by stream", e);
|
||||||
|
}
|
||||||
|
if(mimeType != null) return mimeType;
|
||||||
|
mimeType = URLConnection.guessContentTypeFromName(file.getName());
|
||||||
|
if(mimeType != null) return mimeType;
|
||||||
|
return "*/*";
|
||||||
|
}
|
||||||
|
|
||||||
Intent sendIntent = Intent.createChooser(shareIntent, "latestlog.txt");
|
/**
|
||||||
context.startActivity(sendIntent);
|
* Open the path specified by a File in a file explorer or in a relevant application.
|
||||||
|
* @param context the current Context
|
||||||
|
* @param file the File to open
|
||||||
|
* @param share whether to open a "Share" or an "Open" dialog.
|
||||||
|
*/
|
||||||
|
public static void openPath(Context context, File file, boolean share) {
|
||||||
|
Uri contentUri = DocumentsContract.buildDocumentUri(context.getString(R.string.storageProviderAuthorities), file.getAbsolutePath());
|
||||||
|
String mimeType = getMimeType(file);
|
||||||
|
Intent intent = new Intent();
|
||||||
|
if(share) {
|
||||||
|
intent.setAction(Intent.ACTION_SEND);
|
||||||
|
intent.setType(getMimeType(file));
|
||||||
|
intent.putExtra(Intent.EXTRA_STREAM, contentUri);
|
||||||
|
}else {
|
||||||
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
|
intent.setDataAndType(contentUri, mimeType);
|
||||||
|
}
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
Intent chooserIntent = Intent.createChooser(intent, file.getName());
|
||||||
|
context.startActivity(chooserIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Mesure the textview height, given its current parameters */
|
/** Mesure the textview height, given its current parameters */
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.kdt.pojavlaunch.fragments;
|
package net.kdt.pojavlaunch.fragments;
|
||||||
|
|
||||||
|
import static net.kdt.pojavlaunch.Tools.openPath;
|
||||||
import static net.kdt.pojavlaunch.Tools.shareLog;
|
import static net.kdt.pojavlaunch.Tools.shareLog;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -20,7 +21,12 @@ import net.kdt.pojavlaunch.R;
|
|||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraConstants;
|
import net.kdt.pojavlaunch.extra.ExtraConstants;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraCore;
|
import net.kdt.pojavlaunch.extra.ExtraCore;
|
||||||
|
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||||
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||||
|
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
|
||||||
|
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
public class MainMenuFragment extends Fragment {
|
public class MainMenuFragment extends Fragment {
|
||||||
public static final String TAG = "MainMenuFragment";
|
public static final String TAG = "MainMenuFragment";
|
||||||
@ -38,6 +44,7 @@ public class MainMenuFragment extends Fragment {
|
|||||||
Button mCustomControlButton = view.findViewById(R.id.custom_control_button);
|
Button mCustomControlButton = view.findViewById(R.id.custom_control_button);
|
||||||
Button mInstallJarButton = view.findViewById(R.id.install_jar_button);
|
Button mInstallJarButton = view.findViewById(R.id.install_jar_button);
|
||||||
Button mShareLogsButton = view.findViewById(R.id.share_logs_button);
|
Button mShareLogsButton = view.findViewById(R.id.share_logs_button);
|
||||||
|
Button mOpenDirectoryButton = view.findViewById(R.id.open_files_button);
|
||||||
|
|
||||||
ImageButton mEditProfileButton = view.findViewById(R.id.edit_profile_button);
|
ImageButton mEditProfileButton = view.findViewById(R.id.edit_profile_button);
|
||||||
Button mPlayButton = view.findViewById(R.id.play_button);
|
Button mPlayButton = view.findViewById(R.id.play_button);
|
||||||
@ -57,12 +64,24 @@ public class MainMenuFragment extends Fragment {
|
|||||||
|
|
||||||
mShareLogsButton.setOnClickListener((v) -> shareLog(requireContext()));
|
mShareLogsButton.setOnClickListener((v) -> shareLog(requireContext()));
|
||||||
|
|
||||||
|
mOpenDirectoryButton.setOnClickListener((v)-> openPath(v.getContext(), getCurrentProfileDirectory(), false));
|
||||||
|
|
||||||
|
|
||||||
mNewsButton.setOnLongClickListener((v)->{
|
mNewsButton.setOnLongClickListener((v)->{
|
||||||
Tools.swapFragment(requireActivity(), GamepadMapperFragment.class, GamepadMapperFragment.TAG, null);
|
Tools.swapFragment(requireActivity(), GamepadMapperFragment.class, GamepadMapperFragment.TAG, null);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private File getCurrentProfileDirectory() {
|
||||||
|
String currentProfile = LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE, null);
|
||||||
|
if(!Tools.isValidString(currentProfile)) return new File(Tools.DIR_GAME_NEW);
|
||||||
|
LauncherProfiles.load();
|
||||||
|
MinecraftProfile profileObject = LauncherProfiles.mainProfileJson.profiles.get(currentProfile);
|
||||||
|
if(profileObject == null) return new File(Tools.DIR_GAME_NEW);
|
||||||
|
return Tools.getGameDirPath(profileObject);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
@ -34,6 +34,7 @@ LOCAL_SHARED_LIBRARIES := bytehook
|
|||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
bigcoreaffinity.c \
|
bigcoreaffinity.c \
|
||||||
egl_bridge.c \
|
egl_bridge.c \
|
||||||
|
ctxbridges/loader_dlopen.c \
|
||||||
ctxbridges/gl_bridge.c \
|
ctxbridges/gl_bridge.c \
|
||||||
ctxbridges/osm_bridge.c \
|
ctxbridges/osm_bridge.c \
|
||||||
ctxbridges/egl_loader.c \
|
ctxbridges/egl_loader.c \
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include "egl_loader.h"
|
#include "egl_loader.h"
|
||||||
|
#include "loader_dlopen.h"
|
||||||
|
|
||||||
EGLBoolean (*eglMakeCurrent_p) (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
EGLBoolean (*eglMakeCurrent_p) (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||||
EGLBoolean (*eglDestroyContext_p) (EGLDisplay dpy, EGLContext ctx);
|
EGLBoolean (*eglDestroyContext_p) (EGLDisplay dpy, EGLContext ctx);
|
||||||
@ -24,28 +25,38 @@ EGLint (*eglGetError_p) (void);
|
|||||||
EGLContext (*eglCreateContext_p) (EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
|
EGLContext (*eglCreateContext_p) (EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
|
||||||
EGLBoolean (*eglSwapInterval_p) (EGLDisplay dpy, EGLint interval);
|
EGLBoolean (*eglSwapInterval_p) (EGLDisplay dpy, EGLint interval);
|
||||||
EGLSurface (*eglGetCurrentSurface_p) (EGLint readdraw);
|
EGLSurface (*eglGetCurrentSurface_p) (EGLint readdraw);
|
||||||
|
EGLBoolean (*eglQuerySurface_p)( EGLDisplay display,
|
||||||
|
EGLSurface surface,
|
||||||
|
EGLint attribute,
|
||||||
|
EGLint * value);
|
||||||
|
__eglMustCastToProperFunctionPointerType (*eglGetProcAddress_p) (const char *procname);
|
||||||
|
|
||||||
void dlsym_EGL() {
|
bool dlsym_EGL() {
|
||||||
void* dl_handle = NULL;
|
void* dl_handle = loader_dlopen(getenv("POJAVEXEC_EGL"),"libEGL.so", RTLD_LOCAL|RTLD_LAZY);
|
||||||
if(getenv("POJAVEXEC_EGL")) dl_handle = dlopen(getenv("POJAVEXEC_EGL"), RTLD_LAZY);
|
if(dl_handle == NULL) return false;
|
||||||
if(dl_handle == NULL) dl_handle = dlopen("libEGL.so", RTLD_LAZY);
|
eglGetProcAddress_p = dlsym(dl_handle, "eglGetProcAddress");
|
||||||
if(dl_handle == NULL) abort();
|
if(eglGetProcAddress_p == NULL) {
|
||||||
eglBindAPI_p = dlsym(dl_handle,"eglBindAPI");
|
printf("%s\n", dlerror());
|
||||||
eglChooseConfig_p = dlsym(dl_handle, "eglChooseConfig");
|
return false;
|
||||||
eglCreateContext_p = dlsym(dl_handle, "eglCreateContext");
|
}
|
||||||
eglCreatePbufferSurface_p = dlsym(dl_handle, "eglCreatePbufferSurface");
|
eglBindAPI_p = (void*) eglGetProcAddress_p("eglBindAPI");
|
||||||
eglCreateWindowSurface_p = dlsym(dl_handle, "eglCreateWindowSurface");
|
eglChooseConfig_p = (void*) eglGetProcAddress_p("eglChooseConfig");
|
||||||
eglDestroyContext_p = dlsym(dl_handle, "eglDestroyContext");
|
eglCreateContext_p = (void*) eglGetProcAddress_p("eglCreateContext");
|
||||||
eglDestroySurface_p = dlsym(dl_handle, "eglDestroySurface");
|
eglCreatePbufferSurface_p = (void*) eglGetProcAddress_p("eglCreatePbufferSurface");
|
||||||
eglGetConfigAttrib_p = dlsym(dl_handle, "eglGetConfigAttrib");
|
eglCreateWindowSurface_p = (void*) eglGetProcAddress_p("eglCreateWindowSurface");
|
||||||
eglGetCurrentContext_p = dlsym(dl_handle, "eglGetCurrentContext");
|
eglDestroyContext_p = (void*) eglGetProcAddress_p("eglDestroyContext");
|
||||||
eglGetDisplay_p = dlsym(dl_handle, "eglGetDisplay");
|
eglDestroySurface_p = (void*) eglGetProcAddress_p("eglDestroySurface");
|
||||||
eglGetError_p = dlsym(dl_handle, "eglGetError");
|
eglGetConfigAttrib_p = (void*) eglGetProcAddress_p("eglGetConfigAttrib");
|
||||||
eglInitialize_p = dlsym(dl_handle, "eglInitialize");
|
eglGetCurrentContext_p = (void*) eglGetProcAddress_p("eglGetCurrentContext");
|
||||||
eglMakeCurrent_p = dlsym(dl_handle, "eglMakeCurrent");
|
eglGetDisplay_p = (void*) eglGetProcAddress_p("eglGetDisplay");
|
||||||
eglSwapBuffers_p = dlsym(dl_handle, "eglSwapBuffers");
|
eglGetError_p = (void*) eglGetProcAddress_p("eglGetError");
|
||||||
eglReleaseThread_p = dlsym(dl_handle, "eglReleaseThread");
|
eglInitialize_p = (void*) eglGetProcAddress_p("eglInitialize");
|
||||||
eglSwapInterval_p = dlsym(dl_handle, "eglSwapInterval");
|
eglMakeCurrent_p = (void*) eglGetProcAddress_p("eglMakeCurrent");
|
||||||
eglTerminate_p = dlsym(dl_handle, "eglTerminate");
|
eglSwapBuffers_p = (void*) eglGetProcAddress_p("eglSwapBuffers");
|
||||||
eglGetCurrentSurface_p = dlsym(dl_handle,"eglGetCurrentSurface");
|
eglReleaseThread_p = (void*) eglGetProcAddress_p("eglReleaseThread");
|
||||||
|
eglSwapInterval_p = (void*) eglGetProcAddress_p("eglSwapInterval");
|
||||||
|
eglTerminate_p = (void*) eglGetProcAddress_p("eglTerminate");
|
||||||
|
eglGetCurrentSurface_p = (void*) eglGetProcAddress_p("eglGetCurrentSurface");
|
||||||
|
eglQuerySurface_p = (void*) eglGetProcAddress_p("eglQuerySurface");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Created by maks on 21.09.2022.
|
// Created by maks on 21.09.2022.
|
||||||
//
|
//
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#ifndef POJAVLAUNCHER_EGL_LOADER_H
|
#ifndef POJAVLAUNCHER_EGL_LOADER_H
|
||||||
#define POJAVLAUNCHER_EGL_LOADER_H
|
#define POJAVLAUNCHER_EGL_LOADER_H
|
||||||
|
|
||||||
@ -23,7 +24,12 @@ extern EGLint (*eglGetError_p) (void);
|
|||||||
extern EGLContext (*eglCreateContext_p) (EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
|
extern EGLContext (*eglCreateContext_p) (EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
|
||||||
extern EGLBoolean (*eglSwapInterval_p) (EGLDisplay dpy, EGLint interval);
|
extern EGLBoolean (*eglSwapInterval_p) (EGLDisplay dpy, EGLint interval);
|
||||||
extern EGLSurface (*eglGetCurrentSurface_p) (EGLint readdraw);
|
extern EGLSurface (*eglGetCurrentSurface_p) (EGLint readdraw);
|
||||||
|
extern EGLBoolean (*eglQuerySurface_p)( EGLDisplay display,
|
||||||
|
EGLSurface surface,
|
||||||
|
EGLint attribute,
|
||||||
|
EGLint * value);
|
||||||
|
extern __eglMustCastToProperFunctionPointerType (*eglGetProcAddress_p) (const char *procname);
|
||||||
|
|
||||||
void dlsym_EGL();
|
bool dlsym_EGL();
|
||||||
|
|
||||||
#endif //POJAVLAUNCHER_EGL_LOADER_H
|
#endif //POJAVLAUNCHER_EGL_LOADER_H
|
||||||
|
@ -20,7 +20,7 @@ static __thread gl_render_window_t* currentBundle;
|
|||||||
static EGLDisplay g_EglDisplay;
|
static EGLDisplay g_EglDisplay;
|
||||||
|
|
||||||
bool gl_init() {
|
bool gl_init() {
|
||||||
dlsym_EGL();
|
if(!dlsym_EGL()) return false;
|
||||||
g_EglDisplay = eglGetDisplay_p(EGL_DEFAULT_DISPLAY);
|
g_EglDisplay = eglGetDisplay_p(EGL_DEFAULT_DISPLAY);
|
||||||
if (g_EglDisplay == EGL_NO_DISPLAY) {
|
if (g_EglDisplay == EGL_NO_DISPLAY) {
|
||||||
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s",
|
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s",
|
||||||
@ -39,6 +39,41 @@ gl_render_window_t* gl_get_current() {
|
|||||||
return currentBundle;
|
return currentBundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gl4esi_get_display_dimensions(int* width, int* height) {
|
||||||
|
if(currentBundle == NULL) goto zero;
|
||||||
|
EGLSurface surface = currentBundle->surface;
|
||||||
|
// Fetch dimensions from the EGL surface - the most reliable way
|
||||||
|
EGLBoolean result_width = eglQuerySurface_p(g_EglDisplay, surface, EGL_WIDTH, width);
|
||||||
|
EGLBoolean result_height = eglQuerySurface_p(g_EglDisplay, surface, EGL_HEIGHT, height);
|
||||||
|
if(!result_width || !result_height) goto zero;
|
||||||
|
return;
|
||||||
|
|
||||||
|
zero:
|
||||||
|
// No idea what to do, but feeding gl4es incorrect or non-initialized dimensions may be
|
||||||
|
// a bad idea. Set to zero in case of errors.
|
||||||
|
*width = 0;
|
||||||
|
*height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool already_initialized = false;
|
||||||
|
static void gl_init_gl4es_internals() {
|
||||||
|
if(already_initialized) return;
|
||||||
|
already_initialized = true;
|
||||||
|
void* gl4es = dlopen("libgl4es_114.so", RTLD_NOLOAD);
|
||||||
|
if(gl4es == NULL) return;
|
||||||
|
void (*set_getmainfbsize)(void (*new_getMainFBSize)(int* width, int* height));
|
||||||
|
set_getmainfbsize = dlsym(gl4es, "set_getmainfbsize");
|
||||||
|
if(set_getmainfbsize == NULL) goto warn;
|
||||||
|
set_getmainfbsize(gl4esi_get_display_dimensions);
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
warn:
|
||||||
|
printf("gl4esinternals warning: gl4es was found but internals not initialized. expect rendering issues.\n");
|
||||||
|
cleanup:
|
||||||
|
// dlclose just decreases a ref counter, so this is fine
|
||||||
|
dlclose(gl4es);
|
||||||
|
}
|
||||||
|
|
||||||
gl_render_window_t* gl_init_context(gl_render_window_t *share) {
|
gl_render_window_t* gl_init_context(gl_render_window_t *share) {
|
||||||
gl_render_window_t* bundle = malloc(sizeof(gl_render_window_t));
|
gl_render_window_t* bundle = malloc(sizeof(gl_render_window_t));
|
||||||
memset(bundle, 0, sizeof(gl_render_window_t));
|
memset(bundle, 0, sizeof(gl_render_window_t));
|
||||||
@ -110,6 +145,11 @@ void gl_swap_surface(gl_render_window_t* bundle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void gl_make_current(gl_render_window_t* bundle) {
|
void gl_make_current(gl_render_window_t* bundle) {
|
||||||
|
// Perform initialization here as the renderer may not be loaded when gl_init or gl_init_context is called.
|
||||||
|
// Yes, even though it is dlopened on MC startup by Pojav, due to linker namespacing weirdness
|
||||||
|
// on API 29/MIUI it may not be loaded at the point of the gl_init call in the current namespace.
|
||||||
|
gl_init_gl4es_internals();
|
||||||
|
|
||||||
if(bundle == NULL) {
|
if(bundle == NULL) {
|
||||||
if(eglMakeCurrent_p(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
|
if(eglMakeCurrent_p(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
|
||||||
currentBundle = NULL;
|
currentBundle = NULL;
|
||||||
|
24
app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.c
Normal file
24
app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.c
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by maks on 26.10.2024.
|
||||||
|
//
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <linux/limits.h>
|
||||||
|
void* loader_dlopen(char* primaryName, char* secondaryName, int flags) {
|
||||||
|
void* dl_handle;
|
||||||
|
if(primaryName == NULL) goto secondary;
|
||||||
|
|
||||||
|
dl_handle = dlopen(primaryName, flags);
|
||||||
|
if(dl_handle != NULL) return dl_handle;
|
||||||
|
if(secondaryName == NULL) goto dl_error;
|
||||||
|
|
||||||
|
secondary:
|
||||||
|
dl_handle = dlopen(secondaryName, flags);
|
||||||
|
if(dl_handle == NULL) goto dl_error;
|
||||||
|
return dl_handle;
|
||||||
|
|
||||||
|
dl_error:
|
||||||
|
printf("%s", dlerror());
|
||||||
|
return NULL;
|
||||||
|
}
|
10
app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.h
Normal file
10
app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by maks on 26.10.2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef POJAVLAUNCHER_LOADER_DLOPEN_H
|
||||||
|
#define POJAVLAUNCHER_LOADER_DLOPEN_H
|
||||||
|
|
||||||
|
void* loader_dlopen(char* primaryName, char* secondaryName, int flags);
|
||||||
|
|
||||||
|
#endif //POJAVLAUNCHER_LOADER_DLOPEN_H
|
@ -16,8 +16,8 @@ static char no_render_buffer[4];
|
|||||||
void setNativeWindowSwapInterval(struct ANativeWindow* nativeWindow, int swapInterval);
|
void setNativeWindowSwapInterval(struct ANativeWindow* nativeWindow, int swapInterval);
|
||||||
|
|
||||||
bool osm_init() {
|
bool osm_init() {
|
||||||
dlsym_OSMesa();
|
if(!dlsym_OSMesa()) return false;
|
||||||
return true; // no more specific initialization required
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
osm_render_window_t* osm_get_current() {
|
osm_render_window_t* osm_get_current() {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include "loader_dlopen.h"
|
||||||
#include "osmesa_loader.h"
|
#include "osmesa_loader.h"
|
||||||
|
|
||||||
GLboolean (*OSMesaMakeCurrent_p) (OSMesaContext ctx, void *buffer, GLenum type,
|
GLboolean (*OSMesaMakeCurrent_p) (OSMesaContext ctx, void *buffer, GLenum type,
|
||||||
@ -17,26 +18,25 @@ void (*glFinish_p) (void);
|
|||||||
void (*glClearColor_p) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
void (*glClearColor_p) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||||
void (*glClear_p) (GLbitfield mask);
|
void (*glClear_p) (GLbitfield mask);
|
||||||
void (*glReadPixels_p) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * data);
|
void (*glReadPixels_p) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * data);
|
||||||
|
void* (*OSMesaGetProcAddress_p)(const char* funcName);
|
||||||
|
|
||||||
void dlsym_OSMesa() {
|
bool dlsym_OSMesa() {
|
||||||
char* main_path = NULL;
|
void* dl_handle = loader_dlopen("libOSMesa.so.8", "libOSMesa.so", RTLD_LOCAL | RTLD_LAZY);
|
||||||
char* alt_path = NULL;
|
if(dl_handle == NULL) return false;
|
||||||
if(asprintf(&main_path, "%s/libOSMesa.so", getenv("POJAV_NATIVEDIR")) == -1 ||
|
OSMesaGetProcAddress_p = dlsym(dl_handle, "OSMesaGetProcAddress");
|
||||||
asprintf(&alt_path, "%s/libOSMesa.so.8", getenv("POJAV_NATIVEDIR")) == -1) {
|
if(OSMesaGetProcAddress_p == NULL) {
|
||||||
abort();
|
printf("%s\n", dlerror());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
void* dl_handle = NULL;
|
OSMesaMakeCurrent_p = OSMesaGetProcAddress_p("OSMesaMakeCurrent");
|
||||||
dl_handle = dlopen(alt_path, RTLD_GLOBAL);
|
OSMesaGetCurrentContext_p = OSMesaGetProcAddress_p("OSMesaGetCurrentContext");
|
||||||
if(dl_handle == NULL) dl_handle = dlopen(main_path, RTLD_GLOBAL);
|
OSMesaCreateContext_p = OSMesaGetProcAddress_p("OSMesaCreateContext");
|
||||||
if(dl_handle == NULL) abort();
|
OSMesaDestroyContext_p = OSMesaGetProcAddress_p("OSMesaDestroyContext");
|
||||||
OSMesaMakeCurrent_p = dlsym(dl_handle, "OSMesaMakeCurrent");
|
OSMesaPixelStore_p = OSMesaGetProcAddress_p("OSMesaPixelStore");
|
||||||
OSMesaGetCurrentContext_p = dlsym(dl_handle,"OSMesaGetCurrentContext");
|
glGetString_p = OSMesaGetProcAddress_p("glGetString");
|
||||||
OSMesaCreateContext_p = dlsym(dl_handle, "OSMesaCreateContext");
|
glClearColor_p = OSMesaGetProcAddress_p("glClearColor");
|
||||||
OSMesaDestroyContext_p = dlsym(dl_handle, "OSMesaDestroyContext");
|
glClear_p = OSMesaGetProcAddress_p("glClear");
|
||||||
OSMesaPixelStore_p = dlsym(dl_handle,"OSMesaPixelStore");
|
glFinish_p = OSMesaGetProcAddress_p("glFinish");
|
||||||
glGetString_p = dlsym(dl_handle,"glGetString");
|
glReadPixels_p = OSMesaGetProcAddress_p("glReadPixels");
|
||||||
glClearColor_p = dlsym(dl_handle, "glClearColor");
|
return true;
|
||||||
glClear_p = dlsym(dl_handle,"glClear");
|
|
||||||
glFinish_p = dlsym(dl_handle,"glFinish");
|
|
||||||
glReadPixels_p = dlsym(dl_handle,"glReadPixels");
|
|
||||||
}
|
}
|
@ -6,6 +6,7 @@
|
|||||||
#define POJAVLAUNCHER_OSMESA_LOADER_H
|
#define POJAVLAUNCHER_OSMESA_LOADER_H
|
||||||
|
|
||||||
#include <GL/osmesa.h>
|
#include <GL/osmesa.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
extern GLboolean (*OSMesaMakeCurrent_p) (OSMesaContext ctx, void *buffer, GLenum type,
|
extern GLboolean (*OSMesaMakeCurrent_p) (OSMesaContext ctx, void *buffer, GLenum type,
|
||||||
GLsizei width, GLsizei height);
|
GLsizei width, GLsizei height);
|
||||||
@ -18,5 +19,7 @@ extern void (*glFinish_p) (void);
|
|||||||
extern void (*glClearColor_p) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
extern void (*glClearColor_p) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||||
extern void (*glClear_p) (GLbitfield mask);
|
extern void (*glClear_p) (GLbitfield mask);
|
||||||
extern void (*glReadPixels_p) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * data);
|
extern void (*glReadPixels_p) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * data);
|
||||||
void dlsym_OSMesa();
|
extern void* (*OSMesaGetProcAddress_p)(const char* funcName);
|
||||||
|
|
||||||
|
bool dlsym_OSMesa();
|
||||||
#endif //POJAVLAUNCHER_OSMESA_LOADER_H
|
#endif //POJAVLAUNCHER_OSMESA_LOADER_H
|
||||||
|
@ -546,17 +546,38 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_GLFW_nglfwSetShowingWindow(__attribut
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetWindowAttrib(__attribute__((unused)) JNIEnv* env, __attribute__((unused)) jclass clazz, jint attrib, jint value) {
|
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetWindowAttrib(__attribute__((unused)) JNIEnv* env, __attribute__((unused)) jclass clazz, jint attrib, jint value) {
|
||||||
if (!pojav_environ->showingWindow || !pojav_environ->isUseStackQueueCall) {
|
// Check for stack queue no longer necessary here as the JVM crash's origin is resolved
|
||||||
|
if (!pojav_environ->showingWindow) {
|
||||||
// If the window is not shown, there is nothing to do yet.
|
// If the window is not shown, there is nothing to do yet.
|
||||||
// For Minecraft < 1.13, calling to JNI functions here crashes the JVM for some reason, therefore it is skipped for now.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*pojav_environ->runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
|
// We cannot use pojav_environ->runtimeJNIEnvPtr_JRE here because that environment is attached
|
||||||
pojav_environ->runtimeJNIEnvPtr_JRE,
|
// on the thread that loaded pojavexec (which is the thread that first references the GLFW class)
|
||||||
pojav_environ->vmGlfwClass, pojav_environ->method_glftSetWindowAttrib,
|
// But this method is only called from the Android UI thread
|
||||||
|
|
||||||
|
// Technically the better solution would be to have a permanently attached env pointer stored
|
||||||
|
// in environ for the Android UI thread but this is the only place that uses it
|
||||||
|
// (very rarely, only in lifecycle callbacks) so i dont care
|
||||||
|
|
||||||
|
JavaVM* jvm = pojav_environ->runtimeJavaVMPtr;
|
||||||
|
JNIEnv *jvm_env = NULL;
|
||||||
|
jint env_result = (*jvm)->GetEnv(jvm, (void**)&jvm_env, JNI_VERSION_1_4);
|
||||||
|
if(env_result == JNI_EDETACHED) {
|
||||||
|
env_result = (*jvm)->AttachCurrentThread(jvm, &jvm_env, NULL);
|
||||||
|
}
|
||||||
|
if(env_result != JNI_OK) {
|
||||||
|
printf("input_bridge nativeSetWindowAttrib() JNI call failed: %i\n", env_result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*jvm_env)->CallStaticVoidMethod(
|
||||||
|
jvm_env, pojav_environ->vmGlfwClass,
|
||||||
|
pojav_environ->method_glftSetWindowAttrib,
|
||||||
(jlong) pojav_environ->showingWindow, attrib, value
|
(jlong) pojav_environ->showingWindow, attrib, value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Attaching every time is annoying, so stick the attachment to the Android GUI thread around
|
||||||
}
|
}
|
||||||
const static JNINativeMethod critical_fcns[] = {
|
const static JNINativeMethod critical_fcns[] = {
|
||||||
{"nativeSetUseInputStackQueue", "(Z)V", critical_set_stackqueue},
|
{"nativeSetUseInputStackQueue", "(Z)V", critical_set_stackqueue},
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
app:layout_constraintBottom_toTopOf="@id/mc_version_spinner"
|
app:layout_constraintBottom_toTopOf="@id/_background_display_view"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
@ -30,11 +30,8 @@
|
|||||||
app:layout_constraintGuide_percent="0.5"/>
|
app:layout_constraintGuide_percent="0.5"/>
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/news_button"
|
android:id="@+id/news_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_menu_news"
|
android:drawableStart="@drawable/ic_menu_news"
|
||||||
android:text="@string/mcl_tab_wiki"
|
android:text="@string/mcl_tab_wiki"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@ -42,9 +39,7 @@
|
|||||||
app:layout_constraintEnd_toStartOf="@id/social_divider"/>
|
app:layout_constraintEnd_toStartOf="@id/social_divider"/>
|
||||||
<View
|
<View
|
||||||
android:id="@+id/social_divider"
|
android:id="@+id/social_divider"
|
||||||
android:layout_width="@dimen/padding_tiny"
|
style="@style/LauncherFragment_Divider"
|
||||||
android:layout_height="0dp"
|
|
||||||
android:background="@color/divider"
|
|
||||||
android:layout_marginVertical="@dimen/padding_heavy"
|
android:layout_marginVertical="@dimen/padding_heavy"
|
||||||
app:layout_constraintTop_toTopOf="@id/news_button"
|
app:layout_constraintTop_toTopOf="@id/news_button"
|
||||||
app:layout_constraintStart_toStartOf="@id/center_guideline"
|
app:layout_constraintStart_toStartOf="@id/center_guideline"
|
||||||
@ -52,11 +47,8 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="@id/news_button"/>
|
app:layout_constraintBottom_toBottomOf="@id/news_button"/>
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/discord_button"
|
android:id="@+id/discord_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_discord"
|
android:drawableStart="@drawable/ic_discord"
|
||||||
android:text="@string/mcl_button_discord"
|
android:text="@string/mcl_button_discord"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@ -65,36 +57,37 @@
|
|||||||
|
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/custom_control_button"
|
android:id="@+id/custom_control_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_menu_custom_controls"
|
android:drawableStart="@drawable/ic_menu_custom_controls"
|
||||||
android:text="@string/mcl_option_customcontrol"
|
android:text="@string/mcl_option_customcontrol"
|
||||||
app:layout_constraintTop_toBottomOf="@id/news_button"/>
|
app:layout_constraintTop_toBottomOf="@id/news_button"/>
|
||||||
|
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/install_jar_button"
|
android:id="@+id/install_jar_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_menu_install_jar"
|
android:drawableStart="@drawable/ic_menu_install_jar"
|
||||||
android:text="@string/main_install_jar_file"
|
android:text="@string/main_install_jar_file"
|
||||||
app:layout_constraintTop_toBottomOf="@id/custom_control_button"/>
|
app:layout_constraintTop_toBottomOf="@id/custom_control_button"
|
||||||
|
tools:layout_editor_absoluteX="0dp" />
|
||||||
|
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/share_logs_button"
|
android:id="@+id/share_logs_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@android:drawable/ic_menu_share"
|
android:drawableStart="@android:drawable/ic_menu_share"
|
||||||
android:text="@string/main_share_logs"
|
android:text="@string/main_share_logs"
|
||||||
app:layout_constraintTop_toBottomOf="@id/install_jar_button"/>
|
app:layout_constraintTop_toBottomOf="@id/install_jar_button" />
|
||||||
|
|
||||||
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
|
android:id="@+id/open_files_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:drawableStart="@drawable/ic_folder"
|
||||||
|
android:text="@string/mcl_button_open_directory"
|
||||||
|
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/share_logs_button" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
@ -26,10 +26,8 @@
|
|||||||
app:layout_constraintGuide_percent="0.5"/>
|
app:layout_constraintGuide_percent="0.5"/>
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/news_button"
|
android:id="@+id/news_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/_66sdp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
|
|
||||||
android:text="@string/mcl_tab_wiki"
|
android:text="@string/mcl_tab_wiki"
|
||||||
android:drawableStart="@drawable/ic_menu_news"
|
android:drawableStart="@drawable/ic_menu_news"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@ -37,9 +35,7 @@
|
|||||||
app:layout_constraintEnd_toStartOf="@id/social_divider" />
|
app:layout_constraintEnd_toStartOf="@id/social_divider" />
|
||||||
<View
|
<View
|
||||||
android:id="@+id/social_divider"
|
android:id="@+id/social_divider"
|
||||||
android:layout_width="@dimen/padding_tiny"
|
style="@style/LauncherFragment_Divider"
|
||||||
android:layout_height="0dp"
|
|
||||||
android:background="@color/divider"
|
|
||||||
android:layout_marginVertical="@dimen/padding_large"
|
android:layout_marginVertical="@dimen/padding_large"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="@id/center_guideline"
|
app:layout_constraintStart_toStartOf="@id/center_guideline"
|
||||||
@ -47,10 +43,8 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="@id/news_button"/>
|
app:layout_constraintBottom_toBottomOf="@id/news_button"/>
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/discord_button"
|
android:id="@+id/discord_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/_66sdp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
|
|
||||||
android:text="@string/mcl_button_discord"
|
android:text="@string/mcl_button_discord"
|
||||||
android:drawableStart="@drawable/ic_discord"
|
android:drawableStart="@drawable/ic_discord"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@ -60,36 +54,35 @@
|
|||||||
|
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/custom_control_button"
|
android:id="@+id/custom_control_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/_66sdp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_menu_custom_controls"
|
android:drawableStart="@drawable/ic_menu_custom_controls"
|
||||||
android:text="@string/mcl_option_customcontrol"
|
android:text="@string/mcl_option_customcontrol"
|
||||||
app:layout_constraintTop_toBottomOf="@id/news_button"
|
app:layout_constraintTop_toBottomOf="@id/news_button" />
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/install_jar_button"
|
android:id="@+id/install_jar_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/_66sdp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_menu_install_jar"
|
android:drawableStart="@drawable/ic_menu_install_jar"
|
||||||
android:text="@string/main_install_jar_file"
|
android:text="@string/main_install_jar_file"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/custom_control_button" />
|
||||||
app:layout_constraintTop_toBottomOf="@id/custom_control_button"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<com.kdt.mcgui.LauncherMenuButton
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
android:id="@+id/share_logs_button"
|
android:id="@+id/share_logs_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/_66sdp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@android:drawable/ic_menu_share"
|
android:drawableStart="@android:drawable/ic_menu_share"
|
||||||
android:text="@string/main_share_logs"
|
android:text="@string/main_share_logs"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/install_jar_button" />
|
||||||
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/install_jar_button"
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
/>
|
android:id="@+id/open_files_button"
|
||||||
|
style="@style/LauncherMenuButton.Universal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:drawableStart="@drawable/ic_folder"
|
||||||
|
android:text="@string/mcl_button_open_directory"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/share_logs_button" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
@ -12,4 +12,11 @@
|
|||||||
<item name="android:textSize">@dimen/_14ssp</item>
|
<item name="android:textSize">@dimen/_14ssp</item>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="LauncherMenuButton.Universal" parent="LauncherMenuButton">
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:layout_marginTop">8dp</item>
|
||||||
|
<item name="android:layout_marginBottom">8dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -416,7 +416,8 @@
|
|||||||
<string name="preference_remap_controller_title">Change controller key bindings</string>
|
<string name="preference_remap_controller_title">Change controller key bindings</string>
|
||||||
<string name="preference_remap_controller_description">Allows you to modify the keyboard keys bound to each controller button</string>
|
<string name="preference_remap_controller_description">Allows you to modify the keyboard keys bound to each controller button</string>
|
||||||
<string name="mcl_button_discord">Discord</string>
|
<string name="mcl_button_discord">Discord</string>
|
||||||
<string name="discord_invite" translatable="false">https://discord.gg/pojavlauncher-724163890803638273</string>
|
<string name="mcl_button_open_directory">Open game directory</string>
|
||||||
|
<string name="discord_invite" translatable="false">https://discord.com/invite/aenk3EUvER</string>
|
||||||
<string name="local_login_bad_username_title">Unsuitable username</string>
|
<string name="local_login_bad_username_title">Unsuitable username</string>
|
||||||
<string name="local_login_bad_username_text">The username must be between 3–16 characters long, and must only contain latin letters, arabic numerals and underscores.</string>
|
<string name="local_login_bad_username_text">The username must be between 3–16 characters long, and must only contain latin letters, arabic numerals and underscores.</string>
|
||||||
<string name="quick_setting_title">Quick settings</string>
|
<string name="quick_setting_title">Quick settings</string>
|
||||||
|
@ -13,6 +13,19 @@
|
|||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="LauncherFragment_Divider">
|
||||||
|
<item name="android:layout_width">@dimen/padding_tiny</item>
|
||||||
|
<item name="android:layout_height">0dp</item>
|
||||||
|
<item name="android:background">@color/divider</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="LauncherMenuButton" parent="Widget.AppCompat.Button">
|
||||||
|
<item name="android:background">?android:attr/selectableItemBackground</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="LauncherMenuButton.Universal" parent="LauncherMenuButton">
|
||||||
|
<item name="android:layout_height">@dimen/_66sdp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="ThickDivider">
|
<style name="ThickDivider">
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
@ -508,6 +508,7 @@ public class GLFW
|
|||||||
private static ArrayMap<Long, GLFWWindowProperties> mGLFWWindowMap;
|
private static ArrayMap<Long, GLFWWindowProperties> mGLFWWindowMap;
|
||||||
public static boolean mGLFWIsInputReady;
|
public static boolean mGLFWIsInputReady;
|
||||||
private static boolean mGLFWInputPumping;
|
private static boolean mGLFWInputPumping;
|
||||||
|
private static boolean mGLFWWindowVisibleOnCreation = true;
|
||||||
public static final ByteBuffer keyDownBuffer = ByteBuffer.allocateDirect(317);
|
public static final ByteBuffer keyDownBuffer = ByteBuffer.allocateDirect(317);
|
||||||
public static final ByteBuffer mouseDownBuffer = ByteBuffer.allocateDirect(8);
|
public static final ByteBuffer mouseDownBuffer = ByteBuffer.allocateDirect(8);
|
||||||
|
|
||||||
@ -988,11 +989,15 @@ public class GLFW
|
|||||||
win.height = mGLFWWindowHeight;
|
win.height = mGLFWWindowHeight;
|
||||||
win.title = title;
|
win.title = title;
|
||||||
|
|
||||||
win.windowAttribs.put(GLFW_HOVERED, 1);
|
|
||||||
win.windowAttribs.put(GLFW_VISIBLE, 1);
|
|
||||||
|
|
||||||
mGLFWWindowMap.put(ptr, win);
|
mGLFWWindowMap.put(ptr, win);
|
||||||
mainContext = ptr;
|
mainContext = ptr;
|
||||||
|
|
||||||
|
if(mGLFWWindowVisibleOnCreation || monitor != 0) {
|
||||||
|
// Show window by default if GLFW_VISIBLE hint is specified on creation or
|
||||||
|
// if the monitor is nonnull (fullscreen requested)
|
||||||
|
glfwShowWindow(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
//Return our context
|
//Return our context
|
||||||
}
|
}
|
||||||
@ -1009,7 +1014,9 @@ public class GLFW
|
|||||||
nglfwSetShowingWindow(mGLFWWindowMap.size() == 0 ? 0 : mGLFWWindowMap.keyAt(mGLFWWindowMap.size() - 1));
|
nglfwSetShowingWindow(mGLFWWindowMap.size() == 0 ? 0 : mGLFWWindowMap.keyAt(mGLFWWindowMap.size() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glfwDefaultWindowHints() {}
|
public static void glfwDefaultWindowHints() {
|
||||||
|
mGLFWWindowVisibleOnCreation = true;
|
||||||
|
}
|
||||||
|
|
||||||
public static void glfwGetWindowSize(long window, IntBuffer width, IntBuffer height) {
|
public static void glfwGetWindowSize(long window, IntBuffer width, IntBuffer height) {
|
||||||
if (width != null) width.put(internalGetWindow(window).width);
|
if (width != null) width.put(internalGetWindow(window).width);
|
||||||
@ -1032,10 +1039,17 @@ public class GLFW
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void glfwShowWindow(long window) {
|
public static void glfwShowWindow(long window) {
|
||||||
|
GLFWWindowProperties win = internalGetWindow(window);
|
||||||
|
win.windowAttribs.put(GLFW_HOVERED, 1);
|
||||||
|
win.windowAttribs.put(GLFW_VISIBLE, 1);
|
||||||
nglfwSetShowingWindow(window);
|
nglfwSetShowingWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glfwWindowHint(int hint, int value) {
|
public static void glfwWindowHint(int hint, int value) {
|
||||||
|
if (hint == GLFW_VISIBLE) {
|
||||||
|
mGLFWWindowVisibleOnCreation = value == GLFW_TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
long __functionAddress = Functions.SetWindowHint;
|
long __functionAddress = Functions.SetWindowHint;
|
||||||
invokeV(hint, value, __functionAddress);
|
invokeV(hint, value, __functionAddress);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user