Merge main into backend-virgl (#316)

* Fix Duy's deploy and install stuffs

* Fix Makefile error and move external_include to external/zink

* Bug fix: version ordering when types are disabled

This commit fixes #293

* Update README.md

* Add option to disable symlink to /var/mobile/Documents/.pojavlauncher (off by default)

* Reset preferences option, switch to POJAV_HOME

* Update bug_report.yml

Update pojavlauncher directory location

* Mitigation for the Apache Log4j RCE in 1.8.x-1.18

* Experimental things

* Multitouch handling, allows one of these actions below to work with
moving camera at the same time.
- Switching hotbar slot; might not work properly
- Destroying block (left mouse button) with another finger
long-pressed (without pressing the PRI button)
- Right mouse trigger with another finger tapped onto the screen
(without pressing the SEC button); not working properly yet
* Sub-pixel cursor support; not yet checked

* Completely fix Log4J RCE (1.7-1.16.5) (not yet tested)

TODO: checker with SHA1

* Log4J RCE patch config: disable XML format output

This applies for Minecraft 1.12+
Disable XML formatting for now until we have a log viewer.

* Create newsfeed.html

* Update newsfeed.html

* Delete newsfeed.html

* WIP Demo mode stuff

Sign in with a Microsoft account that doesn't own the game, demo_user will be made. This is very much WIP as my iPhone 7 doesn't feel like launching PojavLauncher.

* New toggle option: Restart before launching game

This option allows the launcher to restart itself before launching the
game, therefore all changes are applied such as JVM Arguments and Java
version. The restart mechanism doesn't always work, so a toggle is
here for now.

* A few UI changes

Disable the Play button until version list finished loading
Disable ability to go back while a version is downloading
Display loading alert while logging in

* Possible fix for broken Mojang login

* Fix a NullPointerException when launching ≤ 1.6.4

* Bug fix: NPE when setting inherited fields

Unable to insert id=null
java.lang.NoSuchFieldException: id
	at java.lang.Class.getDeclaredField(Class.java:2070)
	at net.kdt.pojavlaunch.Tools.insertSafety(Tools.java:544)
	at net.kdt.pojavlaunch.Tools.getVersionInfo(Tools.java:466)
	at net.kdt.pojavlaunch.PLaunchApp.launchMinecraft(PLaunchApp.java:61)
	at
net.kdt.pojavlaunch.uikit.UIKit.callback_SurfaceViewController_launchMi
necraft(UIKit.java:104)
	at net.kdt.pojavlaunch.uikit.UIKit.launchUI(Native Method)
	at net.kdt.pojavlaunch.PLaunchApp.main(PLaunchApp.java:40)

* Keyboard + Mouse input handling; some cleanups
* Keyboard input: KeyboardInput.m
- Requires iOS 13.4. Used pressesBegan and pressesEnded.
- Not all keys are handled, these will be handled later.

* Mouse input
- Requires iOS 13.0 for hovering. Used UIHoverGestureRecognizer.
- Requires iOS 14.0 for L/R mouse buttons and scroll handling. Used GCMouse for now. We will use iOS 13.4(?)'s API later.
- Pointer lock is not yet handled.

These above apply to iPadOS aswell, not sure about tvOS. iPhone users need to disable "Perform Touch Gestures" in the AssistiveTouch Accessibility settings in order to get the pointer hovering to work.

* Cleanups
- Use asprintf instead of sprintf when possible
- CallbackBridge functions: removed unnecessary JNI fields.
- Condition cleanup (managing virtual mouse position).

* Use the old jvm arguments parser back for now

There’s no handling for backslash yet, or ignoring spaces inside delimiters.

* Remove duplicated code

* Support for input cursor movement from keyboard
New class: TrackedTextField. This class keeps track of the pointer in the text field. The hidden text field now has 40 placeholder spaces and the pointer is placed at the middle. When typing, placeholder spaces won't get removed as before. Autocorrect seem to be broken a bit for now.

Additional changes:
- Added missing GLFW functions (array version of other functions)
- Hotbar handling: doubled barWidth and barHeight

Bug fix:
- Touching onto the hotbar breaks the handling of on-screen tap/long-press gestures

* Bug fix: inputStringLength is not set back to 40

This caused a bug that clears the text when pressing backspace after
the keyboard is displayed again.

* Consolidate some code

* Fix undeclared identifier

* Consolidate some more code, fix my dumb mistake

* Added VGPU renderer

Commit:
https://github.com/PojavLauncherTeam/VGPU/commit/9f4ded5934b24c62368d70
1647855c9c9077d903

* Update LauncherPreferencesViewController.m

This line was mistakenly removed

* Various bug fixes
- Input cursor movement seems too fast, attempt to reduce it by setting larger font size in the hidden text field.
- latestlog.txt doesn't log in 1.12+ since Log4j patch. Fixed by adding some config lines.
- Makefile: building is broken when run make from a path with space(s). Fixed by handling spaces with backslashes.
- text2speech is not overridden properly. Fixed by excluding it from download list and adding launcher.jar itself to the classpath.
- XML log output in < 1.12 since Log4j patch. Fixed by using our own configuration file.

Some more changes:
- Commented out a debug line in LWJGLX
- Fix a typo.
- JavaLauncher: use (ObjC)BOOL instead of (std)bool.

* Better click handling

* Finish make ipa

Still requires proper codesigning afterwards, and until I figure out the depends folder you'll need to download a copy of the Azul JDK artifact on our android-openjdk-build-multiarch repository and extract it to depends/jre. Tested and working on my MacBook Pro, although I need to find out why libjsig.dylib is defined twice (this issue doesn't hinder the build though, install_name_tool just doesn't apply changes).

* Added readable MSA errors

* Merge unjailbroken changes with main (#313)

* fix that lol

* IPABuilder moment

* typo moment

* Hooking changes
Now hook only dladdr and realpath, JRE works now. However, need to obtain libffi.

* Sole more changes

Add RPATH to libraries
Hook dlopen since loading libawt_headless somehow point to Frameworks
directory.

* Update development.yml

* Update development.yml

Co-authored-by: Duy Tran Khanh <[email protected]>
Co-authored-by: Duy Tran Khanh <[email protected]>

* Fix issue with text alignment

* Makefile: multi-jobs building native code

* Bump to Xcode 13.2.1

* Bump to Xcode 13.2.1 pt 2

* use gnproc and nproc (for procursus on macos)

on the road development is bumpy

* oops

* [Custom controls] Added color picker for iOS < 14

Might aswell add an option to optionally use this instead of the system
color picker on iOS 14+. Used library: Alderis

Other changes
- [Custom controls] The editor is now fullscreen due to the
presentation of the color picker.
- Fixes scroll wheel input is always int

* I’m too tired of getting dpkg exits, so it’s here

* Fix broken share log

* Bug fix: Fabric 1.17+ crash at startup(fixes #304)

Microsoft account now set accountType to msa.
Minor change in custom control view controller.

* Add Arc capes

* Minor bug fix for Arc capes switch

* Change how the login progress is displayed

Login progress now displays on the title bar instead of a dialog. This
will prevent infinite loading in case a connection error occurs.
Closes #315

* Bug fix: Arc DNS injector breaks on Java 16+

This is caused by a missing function in our class loader.

Error:
System class loader does not define the
appendToClassPathForInstrumentation method
Unable to add
/Applications/PojavLauncher.app/libs/arc_dns_injector.jar to system
class path - the system class loader does not define the
appendToClassPathForInstrumentation method or the method failed
FATAL ERROR in native method: processing of -javaagent failed,
appending to system class path failed

* Why did I add set -e

* Add changelog for 2.1 release

* FAQ changes

* Workflow changes and typo fix

* Workflow changes part 2

* Fixes swipeable button state handling

* Update informational.yml

* Add A7 warning

* Remove codesign from Alderis + thin lib

* Only load Alderis.framework when needed

* CC editor: view controller now follow bounds(#326)

* Update README.md (#324)

* Update LauncherPreferencesViewController.m

Co-authored-by: Duy Tran Khanh <[email protected]>
Co-authored-by: Duy Tran Khanh <[email protected]>
Co-authored-by: Silly Sock <[email protected]>
This commit is contained in:
authored and GitHub committed 2022-02-14 09:13:58 -05:00
1 parent 72e0c69ad1
commit 64f7e82c1e
94 files changed
+3273 -1045

No files matched your search

Binary file not shown.
@@ -2,16 +2,5 @@ package com.mojang.text2speech;
public class Text2Speech {
public static void main(final String[] args) {
System.setProperty("jna.library.path", "./src/natives/resources/");
final Narrator narrator = Narrator.getNarrator();
narrator.say("This is a test", false);
while (true) {
try {
Thread.sleep(100);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
}
@@ -12,51 +12,63 @@ public class JMinecraftVersionList {
public Map<String, String> latest;
public Version[] versions;
public static class Version {
// Since 1.13, so it's one of ways to check
public Arguments arguments;
public static class FileProperties {
public String id, sha1, url;
public long size;
}
public static class Version extends FileProperties {
// Since 1.13, so it's one of ways to check
public Arguments arguments;
public AssetIndex assetIndex;
public String assets;
public Map<String, MinecraftClientInfo> downloads;
public String id;
public String inheritsFrom;
public JavaVersionInfo javaVersion;
public DependentLibrary[] libraries;
public String mainClass;
public String minecraftArguments;
public int minimumLauncherVersion;
public DependentLibrary optifineLib;
public Map<String, MinecraftClientInfo> downloads;
public String inheritsFrom;
public JavaVersionInfo javaVersion;
public DependentLibrary[] libraries;
public LoggingConfig logging;
public String mainClass;
public String minecraftArguments;
public int minimumLauncherVersion;
public DependentLibrary optifineLib;
public String releaseTime;
public String time;
public String type;
public String url;
}
public static class JavaVersionInfo {
public String component;
public int majorVersion;
}
// Since 1.13
public static class Arguments {
public Object[] game;
public Object[] jvm;
public static class LoggingConfig {
public LoggingClientConfig client;
public static class ArgValue {
public ArgRules[] rules;
public String value;
public static class LoggingClientConfig {
public String argument;
public FileProperties file;
public String type;
}
}
// Since 1.13
public static class Arguments {
public Object[] game;
public Object[] jvm;
public static class ArgValue {
public ArgRules[] rules;
public String value;
// TLauncher styled argument...
public String[] values;
public static class ArgRules {
public String action;
public String features;
}
}
}
public static class AssetIndex {
public String id, sha1, url;
public long size, totalSize;
public static class ArgRules {
public String action;
public String features;
}
}
}
public static class AssetIndex extends FileProperties {
public long totalSize;
}
}
@@ -40,10 +40,38 @@ public class PLaunchApp {
UIKit.launchUI();
}
public static String getSelectedVersion() {
try {
String plistContent = Tools.read(Tools.DIR_APP_DATA + "/launcher_preferences.plist");
plistContent = plistContent.substring(plistContent.indexOf("<key>selected_version</key>") + 27);
return plistContent.substring(
plistContent.indexOf("<string>") + 8,
plistContent.indexOf("</string>"));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// Called from SurfaceViewController
public static void launchMinecraft() {
System.out.println("Launching Minecraft " + mVersion.id);
try {
if (AccountJNI.CURRENT_ACCOUNT == null) {
AccountJNI.CURRENT_ACCOUNT = MinecraftAccount.load(System.getProperty("pojav.selectedAccount"));
mVersion = Tools.getVersionInfo(getSelectedVersion());
}
System.out.println("Launching Minecraft " + mVersion.id);
String configPath;
if (mVersion.logging != null) {
if (mVersion.logging.client.file.id.equals("client-1.12.xml")) {
configPath = Tools.DIR_BUNDLE + "/log4j-rce-patch-1.12.xml";
} else if (mVersion.logging.client.file.id.equals("client-1.7.xml")) {
configPath = Tools.DIR_BUNDLE + "/log4j-rce-patch-1.7.xml";
} else {
configPath = Tools.DIR_GAME_NEW + "/" + mVersion.logging.client.file.id;
}
System.setProperty("log4j.configurationFile", configPath);
}
Tools.launchMinecraft(AccountJNI.CURRENT_ACCOUNT, mVersion);
} catch (Throwable th) {
Tools.showError(th);
@@ -57,18 +85,7 @@ public class PLaunchApp {
maxProgress = 0;
UIKit.updateProgressSafe(0, "Finding a version");
String mcver = "1.16.5";
try {
String plistContent = Tools.read(Tools.DIR_APP_DATA + "/launcher_preferences.plist");
plistContent = plistContent.substring(plistContent.indexOf("<key>selected_version</key>") + 27);
mcver = plistContent.substring(
plistContent.indexOf("<string>") + 8,
plistContent.indexOf("</string>"));
} catch (IOException e) {
e.printStackTrace();
UIKit.updateProgressSafe(0, "Could not parse plist, defaulting to Minecraft 1.16.5");
}
String mcver = getSelectedVersion();
AccountJNI.CURRENT_ACCOUNT.selectedVersion = mcver;
try {
@@ -116,6 +133,12 @@ public class PLaunchApp {
e.printStackTrace();
}
if (mVersion.logging != null && !mVersion.logging.client.file.id.equals("client-1.12.xml")) {
UIKit.updateProgressSafe(0, "Downloading " + mVersion.logging.client.file.id);
String configPath = Tools.DIR_GAME_NEW + "/" + mVersion.logging.client.file.id;
Tools.downloadFile(mVersion.logging.client.file.url, configPath);
}
maxProgress = mVersion.libraries.length + 1 + (assets == null ? 0 : assets.objects.size());
File outLib;
@@ -1,5 +1,7 @@
package net.kdt.pojavlaunch;
import java.io.File;
import java.io.IOException;
import java.net.*;
/**
@@ -12,9 +14,40 @@ public class PojavClassLoader extends URLClassLoader {
public PojavClassLoader(ClassLoader parent) {
super(new URL[0], parent);
}
@Override
public void addURL(URL url) {
super.addURL(url);
try {
System.setProperty("java.class.path", System.getProperty("java.class.path") + ":" + new File(url.toURI()).getAbsolutePath());
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
static URL getFileURL(File file) {
try {
file = file.getCanonicalFile();
} catch (IOException e) {}
try {
return file.toURL();
} catch (MalformedURLException e) {
// Should never happen since we specify the protocol...
throw new InternalError(e);
}
}
/**
* This class loader supports dynamic additions to the class path
* at runtime.
*
* @see java.lang.instrument.Instrumentation#appendToSystemClassPathSearch
*/
private void appendToClassPathForInstrumentation(String path) {
assert(Thread.holdsLock(this));
// addURL is a no-op if path already contains the URL
super.addURL(getFileURL(new File(path)));
}
}
@@ -101,12 +101,29 @@ public final class Tools
final String launchClassPath = generateLaunchClassPath(profile.selectedVersion);
List<String> javaArgList = new ArrayList<String>();
//javaArgList.add(versionInfo.logging.client.argument.replace("${path}", DIR_GAME_NEW.getAbsolutePath() + "/" + mVersion.logging.client.file.id));
javaArgList.add("-cp");
javaArgList.add(launchClassPath);
javaArgList.add(versionInfo.mainClass);
javaArgList.addAll(Arrays.asList(launchArgs));
if(profile.username.equals("demo_user")) {
File demoHome = new File(DIR_GAME_HOME + "/demo");
if(demoHome.exists()) {
for (File demoStuff : demoHome.listFiles()) { demoStuff.delete(); }
} else {
demoHome.mkdirs();
}
javaArgList.add("-Duser.home=" + DIR_GAME_HOME + "/demo");
File demoDir = new File(DIR_GAME_NEW + "/demo");
if(demoDir.exists()) {
for (File demoStuff : demoDir.listFiles()) { demoStuff.delete(); }
} else {
demoDir.mkdirs();
}
javaArgList.add("-Duser.dir=" + DIR_GAME_NEW + "/demo");
javaArgList.add("--demo");
}
// Debug
/*
@@ -133,7 +150,8 @@ public final class Tools
// URLClassLoader loader = new URLClassLoader(urlList.toArray(new URL[0]), ClassLoader.getSystemClassLoader());
PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader();
// add launcher.jar itself
loader.addURL(Tools.class.getProtectionDomain().getCodeSource().getLocation().toURI().toURL());
for (String s : launchClassPath.split(":")) {
if (!s.isEmpty()) {
loader.addURL(new File(s).toURI().toURL());
@@ -160,8 +178,6 @@ public final class Tools
if (versionInfo.inheritsFrom != null) {
versionName = versionInfo.inheritsFrom;
}
String userType = "mojang";
File gameDir = new File(Tools.DIR_GAME_NEW);
gameDir.mkdirs();
@@ -170,12 +186,14 @@ public final class Tools
varArgMap.put("auth_access_token", profile.accessToken);
varArgMap.put("auth_player_name", username);
varArgMap.put("auth_uuid", profile.profileId);
// varArgMap.put("auth_xuid", profile.profileId); // TODO!!!
varArgMap.put("assets_root", Tools.ASSETS_PATH);
varArgMap.put("assets_index_name", versionInfo.assets);
varArgMap.put("clientid", profile.clientToken);
varArgMap.put("game_assets", Tools.ASSETS_PATH);
varArgMap.put("game_directory", gameDir.getAbsolutePath());
varArgMap.put("user_properties", "{}");
varArgMap.put("user_type", userType);
varArgMap.put("user_type", profile.isMicrosoft ? "msa" : "mojang");
varArgMap.put("version_name", versionName);
varArgMap.put("version_type", versionInfo.type);
@@ -400,7 +418,7 @@ public final class Tools
// Support for text2speech is not planned, so skip it for now.
for (int i = 0; i < libraries.length; i++) {
DependentLibrary libItem = libraries[i];
if (libItem.name.startsWith("com.mojang.text2speech") ||
if (libItem.name.startsWith("com.mojang:text2speech") ||
libItem.name.startsWith("net.java.jinput") ||
libItem.name.startsWith("net.java.dev.jna:platform:") ||
libItem.name.startsWith("org.lwjgl") ||
@@ -459,7 +477,7 @@ public final class Tools
DependentLibrary libAdded = libList.get(i);
String libAddedName = libAdded.name.substring(0, libAdded.name.lastIndexOf(":"));
if (libAddedName.equals(libName)) {
if (!libAdded.name.equals(lib.name) && libAddedName.equals(libName)) {
System.out.println("Library " + libName + ": Replaced version " +
libAdded.name.substring(libAddedName.length() + 1) + " with " +
lib.name.substring(libName.length() + 1));
@@ -522,10 +540,10 @@ public final class Tools
for (String key : keyArr) {
Object value = null;
try {
Field fieldA = fromVer.getClass().getDeclaredField(key);
Field fieldA = fromVer.getClass().getField(key);
value = fieldA.get(fromVer);
if (((value instanceof String) && !((String) value).isEmpty()) || value != null) {
Field fieldB = targetVer.getClass().getDeclaredField(key);
Field fieldB = targetVer.getClass().getField(key);
fieldB.set(targetVer, value);
}
} catch (Throwable th) {
@@ -46,6 +46,13 @@ public class MicrosoftAuthTask {
acc.profileId = msa.mcUuid;
acc.isMicrosoft = true;
acc.msaRefreshToken = msa.msRefreshToken;
} else if(msa.doesDemo) {
acc.clientToken = "0"; /* FIXME */
acc.accessToken = "-1"; // Differentiate from local accounts
acc.username = "demo_user";
acc.profileId = "25e00594-cf57-3f87-b3af-3f06591be252";
acc.isMicrosoft = false;
acc.msaRefreshToken = "0";
}
acc.save();
@@ -38,6 +38,7 @@ public class Msa {
public String mcToken;
public String mcUuid;
public boolean doesOwnGame;
public boolean doesDemo;
public Msa(MicrosoftAuthTask task, boolean isRefresh, String authCode) throws IOException, JSONException {
this.task = task;
@@ -270,10 +271,16 @@ public class Msa {
// Log.i("MicroAuth","Uuid Minecraft = " + uuidDashes);
mcName=name;
mcUuid=uuidDashes;
}else{
} else if(conn.getResponseCode() == 404) {
// Demo mode stuff
doesOwnGame = false;
doesDemo = true;
} else {
// Log.i("MicroAuth","It seems that this Microsoft Account does not own the game.");
doesOwnGame = false;
doesDemo = false;
throwResponseError(conn);
}
}
@@ -299,9 +306,34 @@ public class Msa {
}
private static void throwResponseError(HttpURLConnection conn) throws IOException {
String otherErrStr = "";
String errStr = Tools.read(conn.getErrorStream());
// Log.i("MicroAuth","Error code: " + conn.getResponseCode() + ": " + conn.getResponseMessage() + "\n" + errStr);
throw new RuntimeException("MSA Error: " + conn.getResponseCode() + ": " + conn.getResponseMessage() + ", error stream:\n" + errStr);
// it seems already handled by the demo mode..
/*
if (errStr.contains("NOT_FOUND") &&
errStr.contains("The server has not found anything matching the request URI"))
{
// TODO localize this
otherErrStr = "It seems that this Microsoft Account does not own the game. Make sure that you have bought/migrated to your Microsoft account.";
} else {
*/
try {
JSONObject jo = new JSONObject(errStr);
switch ((int)(jo.getLong("XErr") - 2148916230l)) {
case 8: // AddChildToFamily
otherErrStr = "This account is under 18 and needs to be added to a Family by an adult before proceed.";
break;
case 3: // CreateAccount
otherErrStr = "The account isn't created yet.";
break;
}
} catch (Throwable th) { // not a JSON?
}
//}
throw new RuntimeException(otherErrStr + "\n\nMSA Error: " + conn.getResponseCode() + ": " + conn.getResponseMessage() + ", error stream:\n" + errStr);
}
}
@@ -17,7 +17,7 @@ public class AccountJNI {
public static volatile MinecraftAccount CURRENT_ACCOUNT;
// Call back about account credentials for login
public static boolean loginAccount(int type,
public static String loginAccount(int type,
String data // One of:
// Local username
// Mojang json response
@@ -61,12 +61,12 @@ public class AccountJNI {
break;
}
return true;
return CURRENT_ACCOUNT.username;
} catch (Throwable th) {
Tools.showError(th);
}
return false;
return null;
}
static {
@@ -12,7 +12,8 @@ public class UIKit {
public static final int ACTION_DOWN = 0;
public static final int ACTION_UP = 1;
public static final int ACTION_MOVE = 2;
public static final int ACTION_MOVE_MOTION = 3;
private static int guiScale;
private static void patch_FlatLAF_setLinux() {
@@ -104,7 +105,7 @@ public class UIKit {
PLaunchApp.launchMinecraft();
}
public static void callback_SurfaceViewController_onTouch(int event, int x, int y) {
public static void callback_SurfaceViewController_onTouch(int event, float x, float y) {
switch (event) {
case ACTION_DOWN:
case ACTION_UP:
@@ -123,6 +124,10 @@ public class UIKit {
CallbackBridge.mouseY = y;
}
break;
case ACTION_MOVE_MOTION:
CallbackBridge.mouseX += x;
CallbackBridge.mouseY += y;
}
CallbackBridge.mouseLastX = x;
CallbackBridge.mouseLastY = y;
@@ -7,7 +7,7 @@ public class MinecraftAccount
{
public String accessToken = "0"; // access token
public String clientToken = "0"; // clientID: refresh and invalidate
public String profileId = "0"; // authenticate UUID
public String profileId = "00000000-0000-0000-0000-000000000000"; // authenticate UUID
public String username = "Steve";
public String selectedVersion = "1.7.10";
public boolean isMicrosoft = false;
@@ -25,7 +25,7 @@ public class CallbackBridge {
public static final int ANDROID_TYPE_GRAB_STATE = 0;
// Should pending events be limited?
volatile public static List<Integer[]> PENDING_EVENT_LIST = new ArrayList<>();
volatile public static List<Object[]> PENDING_EVENT_LIST = new ArrayList<>();
volatile public static boolean PENDING_EVENT_READY = false;
public static final boolean INPUT_DEBUG_ENABLED;
@@ -41,15 +41,15 @@ public class CallbackBridge {
}
// BEGIN launcher side
public static int mouseX, mouseY, mouseLastX, mouseLastY;
public static float mouseX, mouseY, mouseLastX, mouseLastY;
public static boolean mouseLeft;
public static StringBuilder DEBUG_STRING = new StringBuilder();
//public static StringBuilder DEBUG_STRING = new StringBuilder();
public static boolean nativeIsGrabbing() {
return GLFW.mGLFWIsGrabbing;
}
private static void nativeSendCursorPos(int x, int y) {
private static void nativeSendCursorPos(float x, float y) {
if (!inputReady) return;
GLFW.mGLFWCursorX = x + GLFW.internalGetWindow(GLFW.mainContext).x;
GLFW.mGLFWCursorY = y + GLFW.internalGetWindow(GLFW.mainContext).y;
@@ -61,26 +61,26 @@ public class CallbackBridge {
}
private static void nativeSendMouseButton(int button, int action, int mods) {
if (!inputReady) return;
PENDING_EVENT_LIST.add(new Integer[]{EVENT_TYPE_MOUSE_BUTTON, button, action, mods, 0});
PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_MOUSE_BUTTON, button, action, mods, 0});
}
private static void nativeSendScroll(double xoffset, double yoffset) {
if (!inputReady) return;
PENDING_EVENT_LIST.add(new Integer[]{EVENT_TYPE_SCROLL, (int) xoffset, (int) yoffset, 0, 0});
PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_SCROLL, (int) xoffset, (int) yoffset, 0, 0});
}
private static void nativeSendScreenSize(int width, int height) {
if (!inputReady) return;
PENDING_EVENT_LIST.add(new Integer[]{EVENT_TYPE_FRAMEBUFFER_SIZE, width, height, 0, 0});
PENDING_EVENT_LIST.add(new Integer[]{EVENT_TYPE_WINDOW_SIZE, width, height, 0, 0});
PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_FRAMEBUFFER_SIZE, width, height, 0, 0});
PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_WINDOW_SIZE, width, height, 0, 0});
}
private static void nativeSendWindowPos(int x, int y) {
if (!inputReady) return;
PENDING_EVENT_LIST.add(new Integer[]{EVENT_TYPE_WINDOW_POS, x, y, 0, 0});
PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_WINDOW_POS, x, y, 0, 0});
}
// volatile private static boolean isGrabbing = false;
public static class PusherRunnable implements Runnable {
int button; int x; int y;
public PusherRunnable(int button, int x, int y) {
int button; float x; float y;
public PusherRunnable(int button, float x, float y) {
this.button = button;
this.x = x;
this.y = y;
@@ -92,29 +92,29 @@ public class CallbackBridge {
putMouseEventWithCoords(button, 0, x, y);
}
}
public static void putMouseEventWithCoords(int button, int x, int y /* , int dz, long nanos */) {
public static void putMouseEventWithCoords(int button, float x, float y /* , int dz, long nanos */) {
new Thread(new PusherRunnable(button,x,y)).run();
}
public static void putMouseEventWithCoords(int button, int state, int x, int y /* , int dz, long nanos */) {
public static void putMouseEventWithCoords(int button, int state, float x, float y /* , int dz, long nanos */) {
sendCursorPos(x, y);
sendMouseKeycode(button, CallbackBridge.getCurrentMods(), state == 1);
}
private static boolean threadAttached;
public static void sendCursorPos(int x, int y) {
public static void sendCursorPos(float x, float y) {
if (!threadAttached) {
threadAttached = true; // CallbackBridge.nativeAttachThreadToOther(true, true /* TODO BaseMainActivity.isInputStackCall */);
}
DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n");
//DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n");
mouseX = x;
mouseY = y;
nativeSendCursorPos(x, y);
}
public static void sendKeycode(int keycode, char keychar, int scancode, int modifiers, boolean isDown) {
DEBUG_STRING.append("KeyCode=" + keycode + ", Char=" + keychar);
//DEBUG_STRING.append("KeyCode=" + keycode + ", Char=" + keychar);
// TODO CHECK: This may cause input issue, not receive input!
/*
if (!nativeSendCharMods((int) keychar, modifiers) || !nativeSendChar(keychar)) {
@@ -128,7 +128,7 @@ public class CallbackBridge {
}
public static void sendMouseKeycode(int button, int modifiers, boolean isDown) {
DEBUG_STRING.append("MouseKey=" + button + ", down=" + isDown + "\n");
//DEBUG_STRING.append("MouseKey=" + button + ", down=" + isDown + "\n");
// if (isGrabbing()) DEBUG_STRING.append("MouseGrabStrace: " + android.util.Log.getStackTraceString(new Throwable()) + "\n");
nativeSendMouseButton(button, isDown ? 1 : 0, modifiers);
}
@@ -139,7 +139,7 @@ public class CallbackBridge {
}
public static void sendScroll(double xoffset, double yoffset) {
DEBUG_STRING.append("ScrollX=" + xoffset + ",ScrollY=" + yoffset);
//DEBUG_STRING.append("ScrollX=" + xoffset + ",ScrollY=" + yoffset);
nativeSendScroll(xoffset, yoffset);
}
@@ -150,13 +150,7 @@ public class CallbackBridge {
public static boolean isGrabbing() {
return nativeIsGrabbing();
}
public static void sendPrepareGrabInitialPos() {
DEBUG_STRING.append("Prepare set grab initial posititon");
// TODO grab mode
// nativeSendMouseKeycode(-1, CallbackBridge.getCurrentMods(), false);
}
public static boolean holdingAlt, holdingCapslock, holdingCtrl,
holdingNumlock, holdingShift;
public static int getCurrentMods() {
@@ -176,7 +170,7 @@ public class CallbackBridge {
}
// END launcher side
public static void sendGrabbing(boolean grab, int xset, int yset) {
public static void sendGrabbing(boolean grab, float xset, float yset) {
// sendData(ANDROID_TYPE_GRAB_STATE, Boolean.toString(grab));
if (grab) {
@@ -190,8 +184,8 @@ public class CallbackBridge {
nativeSetGrabbing(grab, xset, yset);
}
// Called from Android side
public static void receiveCallback(int type, int i1, int i2, int i3, int i4) {
// Called from native code
public static void receiveCallback(int type, float i1, float i2, int i3, int i4) {
/*
if (INPUT_DEBUG_ENABLED) {
System.out.println("LWJGL GLFW Callback received type=" + Integer.toString(type) + ", data=" + i1 + ", " + i2 + ", " + i3 + ", " + i4);
@@ -199,10 +193,12 @@ public class CallbackBridge {
*/
if (PENDING_EVENT_READY) {
if (type == EVENT_TYPE_CURSOR_POS) {
GLFW.mGLFWCursorX = i1;
GLFW.mGLFWCursorY = i2;
GLFW.mGLFWCursorX = (double) i1;
GLFW.mGLFWCursorY = (double) i2;
} else if (type == EVENT_TYPE_SCROLL) {
PENDING_EVENT_LIST.add(new Object[]{type, i1, i2, i3, i4});
} else {
PENDING_EVENT_LIST.add(new Integer[]{type, i1, i2, i3, i4});
PENDING_EVENT_LIST.add(new Object[]{type, (int)i1, (int)i2, i3, i4});
}
} // else System.out.println("Event input is not ready yet!");
}
@@ -214,6 +210,6 @@ public class CallbackBridge {
}
public static native String nativeClipboard(int action, String copy);
private static native void nativeSetGrabbing(boolean grab, int xset, int yset);
private static native void nativeSetGrabbing(boolean grab, float xset, float yset);
}
+162 -64
View File
@@ -820,29 +820,18 @@ public class GLFW
}
width.put(internalGetWindow(window).width);
height.put(internalGetWindow(window).height);
}
public static void glfwGetFramebufferSize(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") int[] width, @Nullable @NativeType("int *") int[] height) {
if (CHECKS) {
// check(window);
checkSafe(width, 1);
checkSafe(height, 1);
}
width[0] = internalGetWindow(window).width;
height[0] = internalGetWindow(window).height;
}
@Nullable
@Nullable
@NativeType("GLFWmonitor **")
public static PointerBuffer glfwGetMonitors() {
PointerBuffer pBuffer = PointerBuffer.allocateDirect(1);
pBuffer.put(glfwGetPrimaryMonitor());
return pBuffer;
pBuffer.put(glfwGetPrimaryMonitor());
return pBuffer;
}
public static long glfwGetPrimaryMonitor() {
// Prevent NULL check
// Prevent NULL check
return 1L;
}
@@ -870,44 +859,17 @@ public class GLFW
height.put(mGLFWWindowHeight);
}
public static void glfwGetMonitorPos(@NativeType("GLFWmonitor *") long monitor, @Nullable @NativeType("int *") int[] xpos, @Nullable @NativeType("int *") int[] ypos) {
if (CHECKS) {
// check(monitor);
checkSafe(xpos, 1);
checkSafe(ypos, 1);
}
xpos[0] = 0;
ypos[0] = 0;
}
/** Array version of: {@link #glfwGetMonitorWorkarea GetMonitorWorkarea} */
public static void glfwGetMonitorWorkarea(@NativeType("GLFWmonitor *") long monitor, @Nullable @NativeType("int *") int[] xpos, @Nullable @NativeType("int *") int[] ypos, @Nullable @NativeType("int *") int[] width, @Nullable @NativeType("int *") int[] height) {
if (CHECKS) {
// check(monitor);
checkSafe(xpos, 1);
checkSafe(ypos, 1);
checkSafe(width, 1);
checkSafe(height, 1);
}
xpos[0] = 0;
ypos[0] = 0;
width[0] = mGLFWWindowWidth;
height[0] = mGLFWWindowHeight;
}
@NativeType("GLFWmonitor *")
public static long glfwGetWindowMonitor(@NativeType("GLFWwindow *") long window) {
return internalGetWindow(window).monitor;
}
public static void glfwSetWindowMonitor(@NativeType("GLFWwindow *") long window, @NativeType("GLFWmonitor *") long monitor, int xpos, int ypos, int width, int height, int refreshRate) {
GLFWWindowProperties properties = internalGetWindow(window);
properties.monitor = monitor;
properties.x = xpos;
properties.y = ypos;
internalChangeMonitorSize(width, height);
public static void glfwSetWindowMonitor(@NativeType("GLFWwindow *") long window, @NativeType("GLFWmonitor *") long monitor, int xpos, int ypos, int width, int height, int refreshRate) {
GLFWWindowProperties properties = internalGetWindow(window);
properties.monitor = monitor;
properties.x = xpos;
properties.y = ypos;
internalChangeMonitorSize(width, height);
}
public static int glfwGetWindowAttrib(@NativeType("GLFWwindow *") long window, int attrib) {
@@ -1090,7 +1052,7 @@ public class GLFW
// Indirect event
while (CallbackBridge.PENDING_EVENT_LIST.size() > 0) {
Integer[] dataArr = CallbackBridge.PENDING_EVENT_LIST.remove(0);
Object[] dataArr = CallbackBridge.PENDING_EVENT_LIST.remove(0);
if (dataArr == null) { // It should not be null, but still should be catched
// System.out.println("GLFW: popped callback is null, skipping");
@@ -1098,53 +1060,53 @@ public class GLFW
}
for (Long ptr : mGLFWWindowMap.keySet()) {
switch (dataArr[0]) {
switch ((int)dataArr[0]) {
case CallbackBridge.EVENT_TYPE_CHAR:
if (mGLFWCharCallback != null) {
mGLFWCharCallback.invoke(ptr, dataArr[1]);
mGLFWCharCallback.invoke(ptr, (int)dataArr[1]);
}
break;
case CallbackBridge.EVENT_TYPE_CHAR_MODS:
if (mGLFWCharModsCallback != null) {
mGLFWCharModsCallback.invoke(ptr, dataArr[1], dataArr[2]);
mGLFWCharModsCallback.invoke(ptr, (int)dataArr[1], (int)dataArr[2]);
}
break;
case CallbackBridge.EVENT_TYPE_CURSOR_ENTER:
if (mGLFWCursorEnterCallback != null) {
mGLFWCursorEnterCallback.invoke(ptr, dataArr[1] == 1);
mGLFWCursorEnterCallback.invoke(ptr, (int)dataArr[1] == 1);
}
break;
case CallbackBridge.EVENT_TYPE_KEY:
if (mGLFWKeyCallback != null) {
keyDownBuffer[Math.max(0, dataArr[1]-31)]=(byte)(int)dataArr[3];
mGLFWKeyCallback.invoke(ptr, dataArr[1], dataArr[2], dataArr[3], dataArr[4]);
keyDownBuffer[Math.max(0, (int)dataArr[1]-31)]=(byte)(int)dataArr[3];
mGLFWKeyCallback.invoke(ptr, (int)dataArr[1], (int)dataArr[2], (int)dataArr[3], (int)dataArr[4]);
}
break;
case CallbackBridge.EVENT_TYPE_MOUSE_BUTTON:
if (mGLFWMouseButtonCallback != null) {
mGLFWMouseButtonCallback.invoke(ptr, dataArr[1], dataArr[2], dataArr[3]);
mGLFWMouseButtonCallback.invoke(ptr, (int)dataArr[1], (int)dataArr[2], (int)dataArr[3]);
}
break;
case CallbackBridge.EVENT_TYPE_SCROLL:
if (mGLFWScrollCallback != null) {
mGLFWScrollCallback.invoke(ptr, dataArr[1], dataArr[2]);
mGLFWScrollCallback.invoke(ptr, (double)dataArr[1], (double)dataArr[2]);
}
break;
case CallbackBridge.EVENT_TYPE_WINDOW_POS:
glfwSetWindowPos(ptr, dataArr[1], dataArr[2]);
glfwSetWindowPos(ptr, (int)dataArr[1], (int)dataArr[2]);
break;
case CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE:
case CallbackBridge.EVENT_TYPE_WINDOW_SIZE:
internalChangeMonitorSize(dataArr[1], dataArr[2]);
internalChangeMonitorSize((int)dataArr[1], (int)dataArr[2]);
glfwSetWindowSize(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
if (dataArr[0] == CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE && mGLFWFramebufferSizeCallback != null) {
if ((int)dataArr[0] == CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE && mGLFWFramebufferSizeCallback != null) {
mGLFWFramebufferSizeCallback.invoke(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
} else if (dataArr[0] == CallbackBridge.EVENT_TYPE_WINDOW_SIZE && mGLFWWindowSizeCallback != null) {
} else if ((int)dataArr[0] == CallbackBridge.EVENT_TYPE_WINDOW_SIZE && mGLFWWindowSizeCallback != null) {
mGLFWWindowSizeCallback.invoke(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
}
break;
default:
System.err.println("GLFWEvent: unknown callback type " + dataArr[0]);
System.err.println("GLFWEvent: unknown callback type " + (int)dataArr[0]);
break;
}
}
@@ -1156,7 +1118,7 @@ public class GLFW
for (Long ptr : mGLFWWindowMap.keySet()) {
mGLFWCursorPosCallback.invoke(ptr, mGLFWCursorX, mGLFWCursorY);
}
// System.out.println("CursorPos updated to x=" + mGLFWCursorX + ",y=" + mGLFWCursorY);
//System.out.println("CursorPos updated to x=" + mGLFWCursorX + ",y=" + mGLFWCursorY);
}
}
@@ -1302,4 +1264,140 @@ return false;
public static boolean glfwGetGamepadState(int jid, GLFWGamepadState state) {
return false;
}
/** Array version of: {@link #glfwGetVersion GetVersion} */
public static void glfwGetVersion(@Nullable @NativeType("int *") int[] major, @Nullable @NativeType("int *") int[] minor, @Nullable @NativeType("int *") int[] rev) {
if (CHECKS) {
checkSafe(major, 1);
checkSafe(minor, 1);
checkSafe(rev, 1);
}
major[0] = GLFW_VERSION_MAJOR;
minor[0] = GLFW_VERSION_MINOR;
rev[0] = GLFW_VERSION_REVISION;
}
/** Array version of: {@link #glfwGetMonitorPos GetMonitorPos} */
public static void glfwGetMonitorPos(@NativeType("GLFWmonitor *") long monitor, @Nullable @NativeType("int *") int[] xpos, @Nullable @NativeType("int *") int[] ypos) {
if (CHECKS) {
// check(monitor);
checkSafe(xpos, 1);
checkSafe(ypos, 1);
}
xpos[0] = 0;
ypos[0] = 0;
}
/** Array version of: {@link #glfwGetMonitorWorkarea GetMonitorWorkarea} */
public static void glfwGetMonitorWorkarea(@NativeType("GLFWmonitor *") long monitor, @Nullable @NativeType("int *") int[] xpos, @Nullable @NativeType("int *") int[] ypos, @Nullable @NativeType("int *") int[] width, @Nullable @NativeType("int *") int[] height) {
if (CHECKS) {
// check(monitor);
checkSafe(xpos, 1);
checkSafe(ypos, 1);
checkSafe(width, 1);
checkSafe(height, 1);
}
xpos[0] = 0;
ypos[0] = 0;
width[0] = mGLFWWindowWidth;
height[0] = mGLFWWindowHeight;
}
/** Array version of: {@link #glfwGetMonitorPhysicalSize GetMonitorPhysicalSize} */
/*
public static void glfwGetMonitorPhysicalSize(@NativeType("GLFWmonitor *") long monitor, @Nullable @NativeType("int *") int[] widthMM, @Nullable @NativeType("int *") int[] heightMM) {
long __functionAddress = Functions.GetMonitorPhysicalSize;
if (CHECKS) {
check(monitor);
checkSafe(widthMM, 1);
checkSafe(heightMM, 1);
}
invokePPPV(monitor, widthMM, heightMM, __functionAddress);
}
*/
/** Array version of: {@link #glfwGetMonitorContentScale GetMonitorContentScale} */
/*
public static void glfwGetMonitorContentScale(@NativeType("GLFWmonitor *") long monitor, @Nullable @NativeType("float *") float[] xscale, @Nullable @NativeType("float *") float[] yscale) {
long __functionAddress = Functions.GetMonitorContentScale;
if (CHECKS) {
check(monitor);
checkSafe(xscale, 1);
checkSafe(yscale, 1);
}
invokePPPV(monitor, xscale, yscale, __functionAddress);
}
*/
/** Array version of: {@link #glfwGetWindowPos GetWindowPos} */
public static void glfwGetWindowPos(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") int[] xpos, @Nullable @NativeType("int *") int[] ypos) {
if (CHECKS) {
// check(window);
checkSafe(xpos, 1);
checkSafe(ypos, 1);
}
xpos[0] = 0;
ypos[0] = 0;
}
/** Array version of: {@link #glfwGetWindowSize GetWindowSize} */
public static void glfwGetWindowSize(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") int[] width, @Nullable @NativeType("int *") int[] height) {
if (CHECKS) {
// check(window);
checkSafe(width, 1);
checkSafe(height, 1);
}
width[0] = internalGetWindow(window).width;
height[0] = internalGetWindow(window).height;
}
/** Array version of: {@link #glfwGetFramebufferSize GetFramebufferSize} */
public static void glfwGetFramebufferSize(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") int[] width, @Nullable @NativeType("int *") int[] height) {
if (CHECKS) {
// check(window);
checkSafe(width, 1);
checkSafe(height, 1);
}
width[0] = internalGetWindow(window).width;
height[0] = internalGetWindow(window).height;
}
/** Array version of: {@link #glfwGetWindowFrameSize GetWindowFrameSize} */
public static void glfwGetWindowFrameSize(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") int[] left, @Nullable @NativeType("int *") int[] top, @Nullable @NativeType("int *") int[] right, @Nullable @NativeType("int *") int[] bottom) {
if (CHECKS) {
// check(window);
checkSafe(left, 1);
checkSafe(top, 1);
checkSafe(right, 1);
checkSafe(bottom, 1);
}
left[0] = top[0] = 0;
right[0] = internalGetWindow(window).width;
bottom[0] = internalGetWindow(window).height;
}
/** Array version of: {@link #glfwGetWindowContentScale GetWindowContentScale} */
/*
public static void glfwGetWindowContentScale(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("float *") float[] xscale, @Nullable @NativeType("float *") float[] yscale) {
long __functionAddress = Functions.GetWindowContentScale;
if (CHECKS) {
check(window);
checkSafe(xscale, 1);
checkSafe(yscale, 1);
}
invokePPPV(window, xscale, yscale, __functionAddress);
}
*/
/** Array version of: {@link #glfwGetCursorPos GetCursorPos} */
public static void glfwGetCursorPos(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("double *") double[] xpos, @Nullable @NativeType("double *") double[] ypos) {
if (CHECKS) {
// check(window);
checkSafe(xpos, 1);
checkSafe(ypos, 1);
}
xpos[0] = mGLFWCursorX;
ypos[0] = mGLFWCursorY;
}
}
@@ -5,7 +5,7 @@ import java.util.*;
public class GLFWWindowProperties {
public int width = GLFW.mGLFWWindowWidth;
public int height = GLFW.mGLFWWindowHeight;
public int x, y;
public float x, y;
public CharSequence title;
public boolean shouldClose, isInitialSizeCalled, isCursorEntered;
public long monitor;
@@ -178,7 +178,7 @@ public class GLFWInputImplementation implements InputImplementation {
last_event_nanos = nanos;
}
public void putKeyboardEvent(int keycode, byte state, int ch, long nanos, boolean repeat) {
System.out.println("LWJGL2: debug keyboard=" + keycode + ", state=" + state + ", repeat=" + repeat);
//System.out.println("LWJGL2: debug keyboard=" + keycode + ", state=" + state + ", repeat=" + repeat);
key_down_buffer[keycode] = state;
keyboardEvent.clear();
keyboardEvent.putInt(keycode).put(state).putInt(ch).putLong(nanos).put(repeat ? (byte)1 : (byte)0);