cmd/ebitenmobile, internal/devicescale: Experimental fix of the display density

Closes #1481
This commit is contained in:
Hajime Hoshi 2021-02-06 00:27:53 +09:00
parent 1955463296
commit acb8bcae38
3 changed files with 51 additions and 15 deletions

View File

@ -338,18 +338,25 @@ import android.hardware.input.InputManager;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.view.Display;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.InputDevice; import android.view.InputDevice;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager;
import {{.JavaPkg}}.ebitenmobileview.Ebitenmobileview; import {{.JavaPkg}}.ebitenmobileview.Ebitenmobileview;
public class EbitenView extends ViewGroup implements InputManager.InputDeviceListener { public class EbitenView extends ViewGroup implements InputManager.InputDeviceListener {
private double getDeviceScale() { private double getDeviceScale() {
if (this.deviceScale == 0.0) { if (this.deviceScale == 0.0) {
this.deviceScale = getResources().getDisplayMetrics().density; WindowManager windowManager = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getRealMetrics(displayMetrics);
this.deviceScale = displayMetrics.density;
} }
return this.deviceScale; return this.deviceScale;
} }

File diff suppressed because one or more lines are too long

View File

@ -19,36 +19,65 @@ package devicescale
#include <jni.h> #include <jni.h>
#include <stdlib.h> #include <stdlib.h>
// Basically same as `getResources().getDisplayMetrics().density`; // Basically same as:
//
// WindowService windowService = context.getSystemService(Context.WINDOW_SERVICE);
// Display display = windowManager.getDefaultDisplay();
// DisplayMetrics displayMetrics = new DisplayMetrics();
// display.getRealMetrics(displayMetrics);
// this.deviceScale = displayMetrics.density;
//
static float deviceScale(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx) { static float deviceScale(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx) {
JavaVM* vm = (JavaVM*)java_vm; JavaVM* vm = (JavaVM*)java_vm;
JNIEnv* env = (JNIEnv*)jni_env; JNIEnv* env = (JNIEnv*)jni_env;
jobject context = (jobject)ctx; jobject context = (jobject)ctx;
const jclass android_content_ContextWrapper = const char* kWindowService = "window";
(*env)->FindClass(env, "android/content/ContextWrapper");
const jclass android_content_res_Resources = const jclass android_content_Context =
(*env)->FindClass(env, "android/content/res/Resources"); (*env)->FindClass(env, "android/content/Context");
const jclass android_view_WindowManager =
(*env)->FindClass(env, "android/view/WindowManager");
const jclass android_view_Display =
(*env)->FindClass(env, "android/view/Display");
const jclass android_util_DisplayMetrics = const jclass android_util_DisplayMetrics =
(*env)->FindClass(env, "android/util/DisplayMetrics"); (*env)->FindClass(env, "android/util/DisplayMetrics");
const jobject resources = const jobject android_context_Context_WINDOW_SERVICE =
(*env)->GetStaticObjectField(
env, android_content_Context,
(*env)->GetStaticFieldID(env, android_content_Context, "WINDOW_SERVICE", "Ljava/lang/String;"));
const jobject windowManager =
(*env)->CallObjectMethod( (*env)->CallObjectMethod(
env, context, env, context,
(*env)->GetMethodID(env, android_content_ContextWrapper, "getResources", "()Landroid/content/res/Resources;")); (*env)->GetMethodID(env, android_content_Context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"),
const jobject displayMetrics = android_context_Context_WINDOW_SERVICE);
const jobject display =
(*env)->CallObjectMethod( (*env)->CallObjectMethod(
env, resources, env, windowManager,
(*env)->GetMethodID(env, android_content_res_Resources, "getDisplayMetrics", "()Landroid/util/DisplayMetrics;")); (*env)->GetMethodID(env, android_view_WindowManager, "getDefaultDisplay", "()Landroid/view/Display;"));
const jobject displayMetrics =
(*env)->NewObject(
  env, android_util_DisplayMetrics,
(*env)->GetMethodID(env, android_util_DisplayMetrics, "<init>", "()V"));
(*env)->CallVoidMethod(
env, display,
(*env)->GetMethodID(env, android_view_Display, "getRealMetrics", "(Landroid/util/DisplayMetrics;)V"),
displayMetrics);
const float density = const float density =
(*env)->GetFloatField( (*env)->GetFloatField(
env, displayMetrics, env, displayMetrics,
(*env)->GetFieldID(env, android_util_DisplayMetrics, "density", "F")); (*env)->GetFieldID(env, android_util_DisplayMetrics, "density", "F"));
(*env)->DeleteLocalRef(env, android_content_ContextWrapper); (*env)->DeleteLocalRef(env, android_content_Context);
(*env)->DeleteLocalRef(env, android_content_res_Resources); (*env)->DeleteLocalRef(env, android_view_WindowManager);
(*env)->DeleteLocalRef(env, android_view_Display);
(*env)->DeleteLocalRef(env, android_util_DisplayMetrics); (*env)->DeleteLocalRef(env, android_util_DisplayMetrics);
(*env)->DeleteLocalRef(env, resources);
(*env)->DeleteLocalRef(env, android_context_Context_WINDOW_SERVICE);
(*env)->DeleteLocalRef(env, windowManager);
(*env)->DeleteLocalRef(env, display);
(*env)->DeleteLocalRef(env, displayMetrics); (*env)->DeleteLocalRef(env, displayMetrics);
return density; return density;