|
@@ -52,12 +52,11 @@
|
|
|
#endif
|
|
|
#ifdef LAGUI_ANDROID
|
|
|
#include <GLES3/gl32.h>
|
|
|
+#include <jni.h>
|
|
|
#include <android/log.h>
|
|
|
#include <android/native_activity.h>
|
|
|
-#include <jni.h>
|
|
|
#include <android/native_window.h>
|
|
|
#include <android/native_window_jni.h>
|
|
|
-#include <jni.h>
|
|
|
#include <android_native_app_glue.h>
|
|
|
#include <android/window.h>
|
|
|
#include <android/asset_manager.h>
|
|
@@ -1306,11 +1305,15 @@ int laGetReadyWith(laInitArguments* ia){
|
|
|
MAIN.WireThickness = 5;
|
|
|
MAIN.WireSaggyness = 0.5;
|
|
|
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ laAddResourceFolder("");
|
|
|
+#else
|
|
|
laAddResourceFolder(".");
|
|
|
+#endif
|
|
|
|
|
|
laSetMenuBarTemplates(laui_DefaultMenuButtons, laui_DefaultMenuExtras, "🧩LaGUI 2022");
|
|
|
|
|
|
- laAddExtraExtension(LA_FILETYPE_UDF,"udf",0);
|
|
|
+ laAddExtraExtension(LA_FILETYPE_UDF,"udf",0ll);
|
|
|
|
|
|
la_InitProgressWindow();
|
|
|
la_MakeTranslations();
|
|
@@ -1442,12 +1445,22 @@ void laShutoff(int SavePrefereces){
|
|
|
}
|
|
|
|
|
|
int laRestoreFactorySettings(){
|
|
|
- char path[1024]; sprintf(path, "%s%s", SSTR(MAIN.WorkingDirectory), "preferences.udf");
|
|
|
+ char path[1024];
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ sprintf(path,"%s","preferences.udf");
|
|
|
+#else
|
|
|
+ sprintf(path,"%s%s",SSTR(MAIN.WorkingDirectory),"preferences.udf");
|
|
|
+#endif
|
|
|
if(remove(path)){ return 0; }
|
|
|
return 1;
|
|
|
}
|
|
|
void laSaveUserPreferences(){
|
|
|
- char path[1024]; sprintf(path,"%s%s",SSTR(MAIN.WorkingDirectory),"preferences.udf");
|
|
|
+ char path[1024];
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ sprintf(path,"%s","preferences.udf");
|
|
|
+#else
|
|
|
+ sprintf(path,"%s%s",SSTR(MAIN.WorkingDirectory),"preferences.udf");
|
|
|
+#endif
|
|
|
laUDF* udf=laPrepareUDF(path);
|
|
|
laWriteProp(udf,"la.windows");
|
|
|
laWriteProp(udf,"la.user_preferences");
|
|
@@ -1459,10 +1472,15 @@ void laSaveUserPreferences(){
|
|
|
laPackUDF(udf,0,0);
|
|
|
}
|
|
|
void laEnsureUserPreferences(){
|
|
|
- char path[1024]; sprintf(path,"%s%s",SSTR(MAIN.WorkingDirectory),"preferences.udf");
|
|
|
+ char path[1024];
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ sprintf(path,"%s/%s",MAIN.InternalDataPath,"preferences.udf");
|
|
|
+#else
|
|
|
+ sprintf(path,"%s%s",SSTR(MAIN.WorkingDirectory),"preferences.udf");
|
|
|
+#endif
|
|
|
laUDFRegistry* r=laFindUDFRegistry(path);
|
|
|
if(!r){ laSaveUserPreferences(); return; }
|
|
|
- laUDF* udf=laOpenUDF(r->Path->Ptr,1,0,0); if(!udf){ logPrint("Can't read preferences. Using default settings."); return; }
|
|
|
+ laUDF* udf=laOpenUDF(SSTR(r->Path),1,0,0); if(!udf){ logPrint("Can't read preferences on %s. Using default settings.",SSTR(r->Path)); return; }
|
|
|
laClearUDFRegistries();
|
|
|
while(MAIN.ResourceFolders.pFirst){ laRemoveResourceFolder(MAIN.ResourceFolders.pFirst); }
|
|
|
while(MAIN.InputMapping->InputMappings.pFirst){ laRemoveInputMapping(MAIN.InputMapping->InputMappings.pFirst); }
|
|
@@ -1482,6 +1500,7 @@ void laAddExtraExtension(int FileType, ...){
|
|
|
laExtensionType* et=memAcquireSimple(sizeof(laExtensionType));
|
|
|
et->FileType=FileType; et->Extension=ext;
|
|
|
lstAppendItem(&MAIN.ExtraExtensions, et);
|
|
|
+ logPrintNew("add ext %s",ext);
|
|
|
}
|
|
|
va_end(list);
|
|
|
}
|
|
@@ -3075,6 +3094,9 @@ void la_AssignWindowPP(laWindow* w){
|
|
|
w->PP.LastPs->Type = U'.';
|
|
|
}
|
|
|
laWindow *laDesignWindow(int X, int Y, int W, int H){
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ if(MAIN.Windows.pFirst){ return MAIN.Windows.pFirst; }
|
|
|
+#endif
|
|
|
laWindow *n = memAcquire(sizeof(laWindow));
|
|
|
|
|
|
strSafeSet(&n->Title, "Empty SYSWINDOW");
|
|
@@ -8041,6 +8063,11 @@ void laMainLoop(){
|
|
|
|
|
|
laSetWindowCursor(LA_ARROW);
|
|
|
MAIN.DelayTriggered=1;
|
|
|
+
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ while(!MAIN.AppReady){ usleep(1000); }
|
|
|
+ la_CommandResizeWindow(0,0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
+#endif
|
|
|
|
|
|
while (1){
|
|
|
laRecordTime(&FrameStartTime);
|
|
@@ -8110,6 +8137,8 @@ int la_AndroidInitGraphics(void){
|
|
|
MAIN.AppWidth=ANativeWindow_getWidth(MAIN.app->window);
|
|
|
MAIN.AppHeight=ANativeWindow_getHeight(MAIN.app->window);
|
|
|
|
|
|
+ logPrintNew("Android init graphics %d x %d", MAIN.AppWidth, MAIN.AppHeight);
|
|
|
+
|
|
|
la_CommandResizeWindow(0,0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
|
|
|
EGLint samples = 0;
|
|
@@ -8132,7 +8161,7 @@ int la_AndroidInitGraphics(void){
|
|
|
|
|
|
EGLint numConfigs = 0;
|
|
|
|
|
|
- MAIN.egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
|
+ MAIN.egl_dpy=eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
|
if (MAIN.egl_dpy == EGL_NO_DISPLAY){ logPrint("Android no display"); return -1; }
|
|
|
if (eglInitialize(MAIN.egl_dpy, NULL, NULL) == EGL_FALSE){ logPrint("Android can't init display"); return -1; }
|
|
|
eglChooseConfig(MAIN.egl_dpy, framebufferAttribs, &MAIN.BestFBC, 1, &numConfigs);
|
|
@@ -8146,16 +8175,13 @@ int la_AndroidInitGraphics(void){
|
|
|
|
|
|
ANativeWindow_setBuffersGeometry(MAIN.app->window, MAIN.AppWidth, MAIN.AppHeight, displayFormat);
|
|
|
|
|
|
- MAIN.egl_surf = eglCreateWindowSurface(MAIN.egl_surf, MAIN.BestFBC, MAIN.app->window, NULL);
|
|
|
+ MAIN.egl_surf = eglCreateWindowSurface(MAIN.egl_dpy, MAIN.BestFBC, MAIN.app->window, NULL);
|
|
|
|
|
|
// There must be at least one frame displayed before the buffers are swapped
|
|
|
- //eglSwapInterval(MAIN.egl_dpy, 1);
|
|
|
+ eglSwapInterval(MAIN.egl_dpy, 1);
|
|
|
|
|
|
if (eglMakeCurrent(MAIN.egl_dpy, MAIN.egl_surf, MAIN.egl_surf, MAIN.glc) == EGL_FALSE) { logPrint("Android can't make current"); return -1; }
|
|
|
-
|
|
|
- glViewport(0,0,MAIN.AppWidth, MAIN.AppHeight);
|
|
|
- glClearColor(0,1,1,1);
|
|
|
- glClear(GL_COLOR_BUFFER_BIT);
|
|
|
+
|
|
|
eglSwapBuffers(MAIN.egl_dpy, MAIN.egl_surf);
|
|
|
|
|
|
MAIN.AppReady = 1;
|
|
@@ -8192,7 +8218,7 @@ static void la_AndroidCommandCallback(struct android_app *app, int32_t cmd){
|
|
|
//glViewport(0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
//glClearColor(1,0.2,1,1);
|
|
|
//glClear(GL_COLOR_BUFFER_BIT);
|
|
|
- eglSwapBuffers(MAIN.egl_dpy, MAIN.egl_surf);
|
|
|
+ //eglSwapBuffers(MAIN.egl_dpy, MAIN.egl_surf);
|
|
|
la_CommandResizeWindow(0,0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
|
|
|
MAIN.ContextRebindRequired = false;
|
|
@@ -8223,6 +8249,7 @@ static void la_AndroidCommandCallback(struct android_app *app, int32_t cmd){
|
|
|
case APP_CMD_CONFIG_CHANGED:
|
|
|
MAIN.AppWidth=ANativeWindow_getWidth(MAIN.app->window);
|
|
|
MAIN.AppHeight=ANativeWindow_getHeight(MAIN.app->window);
|
|
|
+
|
|
|
la_CommandResizeWindow(0,0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
//AConfiguration_fromAssetManager(MAIN.app->config, MAIN.app->activity->assetManager);
|
|
|
//print_cur_config(MAIN.app);
|
|
@@ -8233,6 +8260,172 @@ static void la_AndroidCommandCallback(struct android_app *app, int32_t cmd){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#define KEYCODE_MAP_SIZE 162
|
|
|
+static const int KeycodeMap[KEYCODE_MAP_SIZE] = {
|
|
|
+ 0, // AKEYCODE_UNKNOWN
|
|
|
+ 0, // AKEYCODE_SOFT_LEFT
|
|
|
+ 0, // AKEYCODE_SOFT_RIGHT
|
|
|
+ 0, // AKEYCODE_HOME
|
|
|
+ 0, // AKEYCODE_BACK
|
|
|
+ 0, // AKEYCODE_CALL
|
|
|
+ 0, // AKEYCODE_ENDCALL
|
|
|
+ '0', // AKEYCODE_0
|
|
|
+ '1', // AKEYCODE_1
|
|
|
+ '2', // AKEYCODE_2
|
|
|
+ '3', // AKEYCODE_3
|
|
|
+ '4', // AKEYCODE_4
|
|
|
+ '5', // AKEYCODE_5
|
|
|
+ '6', // AKEYCODE_6
|
|
|
+ '7', // AKEYCODE_7
|
|
|
+ '8', // AKEYCODE_8
|
|
|
+ '9', // AKEYCODE_9
|
|
|
+ 0, // AKEYCODE_STAR
|
|
|
+ 0, // AKEYCODE_POUND
|
|
|
+ LA_KEY_ARRUP, // AKEYCODE_DPAD_UP
|
|
|
+ LA_KEY_ARRDOWN, // AKEYCODE_DPAD_DOWN
|
|
|
+ LA_KEY_ARRLEFT, // AKEYCODE_DPAD_LEFT
|
|
|
+ LA_KEY_ARRRIGHT, // AKEYCODE_DPAD_RIGHT
|
|
|
+ 0, // AKEYCODE_DPAD_CENTER
|
|
|
+ 0, // AKEYCODE_VOLUME_UP
|
|
|
+ 0, // AKEYCODE_VOLUME_DOWN
|
|
|
+ 0, // AKEYCODE_POWER
|
|
|
+ 0, // AKEYCODE_CAMERA
|
|
|
+ 0, // AKEYCODE_CLEAR
|
|
|
+ 'a', // AKEYCODE_A
|
|
|
+ 'b', // AKEYCODE_B
|
|
|
+ 'c', // AKEYCODE_C
|
|
|
+ 'd', // AKEYCODE_D
|
|
|
+ 'e', // AKEYCODE_E
|
|
|
+ 'f', // AKEYCODE_F
|
|
|
+ 'g', // AKEYCODE_G
|
|
|
+ 'h', // AKEYCODE_H
|
|
|
+ 'i', // AKEYCODE_I
|
|
|
+ 'j', // AKEYCODE_J
|
|
|
+ 'k', // AKEYCODE_K
|
|
|
+ 'l', // AKEYCODE_L
|
|
|
+ 'm', // AKEYCODE_M
|
|
|
+ 'n', // AKEYCODE_N
|
|
|
+ 'o', // AKEYCODE_O
|
|
|
+ 'p', // AKEYCODE_P
|
|
|
+ 'q', // AKEYCODE_Q
|
|
|
+ 'r', // AKEYCODE_R
|
|
|
+ 's', // AKEYCODE_S
|
|
|
+ 't', // AKEYCODE_T
|
|
|
+ 'u', // AKEYCODE_U
|
|
|
+ 'v', // AKEYCODE_V
|
|
|
+ 'w', // AKEYCODE_W
|
|
|
+ 'x', // AKEYCODE_X
|
|
|
+ 'y', // AKEYCODE_Y
|
|
|
+ 'z', // AKEYCODE_Z
|
|
|
+ ',', // AKEYCODE_COMMA
|
|
|
+ '.', // AKEYCODE_PERIOD
|
|
|
+ LA_KEY_ALT, // AKEYCODE_ALT_LEFT
|
|
|
+ LA_KEY_ALT, // AKEYCODE_ALT_RIGHT
|
|
|
+ LA_KEY_SHIFT, // AKEYCODE_SHIFT_LEFT
|
|
|
+ LA_KEY_SHIFT, // AKEYCODE_SHIFT_RIGHT
|
|
|
+ LA_KEY_TAB, // AKEYCODE_TAB
|
|
|
+ ' ', // AKEYCODE_SPACE
|
|
|
+ 0, // AKEYCODE_SYM
|
|
|
+ 0, // AKEYCODE_EXPLORER
|
|
|
+ 0, // AKEYCODE_ENVELOPE
|
|
|
+ LA_KEY_ENTER, // AKEYCODE_ENTER
|
|
|
+ LA_KEY_BACKSPACE, // AKEYCODE_DEL
|
|
|
+ '`', // AKEYCODE_GRAVE
|
|
|
+ '-', // AKEYCODE_MINUS
|
|
|
+ '=', // AKEYCODE_EQUALS
|
|
|
+ '(', // AKEYCODE_LEFT_BRACKET
|
|
|
+ ')', // AKEYCODE_RIGHT_BRACKET
|
|
|
+ '\\', // AKEYCODE_BACKSLASH
|
|
|
+ ';', // AKEYCODE_SEMICOLON
|
|
|
+ '\'', // AKEYCODE_APOSTROPHE
|
|
|
+ '/', // AKEYCODE_SLASH
|
|
|
+ 0, // AKEYCODE_AT
|
|
|
+ 0, // AKEYCODE_NUM
|
|
|
+ 0, // AKEYCODE_HEADSETHOOK
|
|
|
+ 0, // AKEYCODE_FOCUS
|
|
|
+ 0, // AKEYCODE_PLUS
|
|
|
+ 0, // AKEYCODE_MENU
|
|
|
+ 0, // AKEYCODE_NOTIFICATION
|
|
|
+ 0, // AKEYCODE_SEARCH
|
|
|
+ 0, // AKEYCODE_MEDIA_PLAY_PAUSE
|
|
|
+ 0, // AKEYCODE_MEDIA_STOP
|
|
|
+ 0, // AKEYCODE_MEDIA_NEXT
|
|
|
+ 0, // AKEYCODE_MEDIA_PREVIOUS
|
|
|
+ 0, // AKEYCODE_MEDIA_REWIND
|
|
|
+ 0, // AKEYCODE_MEDIA_FAST_FORWARD
|
|
|
+ 0, // AKEYCODE_MUTE
|
|
|
+ 0, // AKEYCODE_PAGE_UP
|
|
|
+ 0, // AKEYCODE_PAGE_DOWN
|
|
|
+ 0, // AKEYCODE_PICTSYMBOLS
|
|
|
+ 0, // AKEYCODE_SWITCH_CHARSET
|
|
|
+ 0, // AKEYCODE_BUTTON_A
|
|
|
+ 0, // AKEYCODE_BUTTON_B
|
|
|
+ 0, // AKEYCODE_BUTTON_C
|
|
|
+ 0, // AKEYCODE_BUTTON_X
|
|
|
+ 0, // AKEYCODE_BUTTON_Y
|
|
|
+ 0, // AKEYCODE_BUTTON_Z
|
|
|
+ 0, // AKEYCODE_BUTTON_L1
|
|
|
+ 0, // AKEYCODE_BUTTON_R1
|
|
|
+ 0, // AKEYCODE_BUTTON_L2
|
|
|
+ 0, // AKEYCODE_BUTTON_R2
|
|
|
+ 0, // AKEYCODE_BUTTON_THUMBL
|
|
|
+ 0, // AKEYCODE_BUTTON_THUMBR
|
|
|
+ 0, // AKEYCODE_BUTTON_START
|
|
|
+ 0, // AKEYCODE_BUTTON_SELECT
|
|
|
+ 0, // AKEYCODE_BUTTON_MODE
|
|
|
+ LA_KEY_ESCAPE, // AKEYCODE_ESCAPE
|
|
|
+ LA_KEY_DELETE, // AKEYCODE_FORWARD_DELL
|
|
|
+ LA_KEY_CTRL, // AKEYCODE_CTRL_LEFT
|
|
|
+ LA_KEY_CTRL, // AKEYCODE_CTRL_RIGHT
|
|
|
+ 0, // AKEYCODE_CAPS_LOCK
|
|
|
+ 0, // AKEYCODE_SCROLL_LOCK
|
|
|
+ LA_KEY_ARRLEFT, // AKEYCODE_META_LEFT
|
|
|
+ LA_KEY_ARRRIGHT, // AKEYCODE_META_RIGHT
|
|
|
+ 0, // AKEYCODE_FUNCTION
|
|
|
+ 0, // AKEYCODE_SYSRQ
|
|
|
+ 0, // AKEYCODE_BREAK
|
|
|
+ 0, // AKEYCODE_MOVE_HOME
|
|
|
+ 0, // AKEYCODE_MOVE_END
|
|
|
+ 0, // AKEYCODE_INSERT
|
|
|
+ 0, // AKEYCODE_FORWARD
|
|
|
+ 0, // AKEYCODE_MEDIA_PLAY
|
|
|
+ 0, // AKEYCODE_MEDIA_PAUSE
|
|
|
+ 0, // AKEYCODE_MEDIA_CLOSE
|
|
|
+ 0, // AKEYCODE_MEDIA_EJECT
|
|
|
+ 0, // AKEYCODE_MEDIA_RECORD
|
|
|
+ LA_KEY_F1, // AKEYCODE_F1
|
|
|
+ LA_KEY_F2, // AKEYCODE_F2
|
|
|
+ LA_KEY_F3, // AKEYCODE_F3
|
|
|
+ LA_KEY_F4, // AKEYCODE_F4
|
|
|
+ LA_KEY_F5, // AKEYCODE_F5
|
|
|
+ LA_KEY_F6, // AKEYCODE_F6
|
|
|
+ LA_KEY_F7, // AKEYCODE_F7
|
|
|
+ LA_KEY_F8, // AKEYCODE_F8
|
|
|
+ LA_KEY_F9, // AKEYCODE_F9
|
|
|
+ LA_KEY_F10, // AKEYCODE_F10
|
|
|
+ LA_KEY_F11, // AKEYCODE_F11
|
|
|
+ LA_KEY_F12, // AKEYCODE_F12
|
|
|
+ 0, // AKEYCODE_NUM_LOCK
|
|
|
+ LA_KEY_NUM0, // AKEYCODE_NUMPAD_0
|
|
|
+ LA_KEY_NUM1, // AKEYCODE_NUMPAD_1
|
|
|
+ LA_KEY_NUM2, // AKEYCODE_NUMPAD_2
|
|
|
+ LA_KEY_NUM3, // AKEYCODE_NUMPAD_3
|
|
|
+ LA_KEY_NUM4, // AKEYCODE_NUMPAD_4
|
|
|
+ LA_KEY_NUM5, // AKEYCODE_NUMPAD_5
|
|
|
+ LA_KEY_NUM6, // AKEYCODE_NUMPAD_6
|
|
|
+ LA_KEY_NUM7, // AKEYCODE_NUMPAD_7
|
|
|
+ LA_KEY_NUM8, // AKEYCODE_NUMPAD_8
|
|
|
+ LA_KEY_NUM9, // AKEYCODE_NUMPAD_9
|
|
|
+ LA_KEY_NUMDIVIDE, // AKEYCODE_NUMPAD_DIVIDE
|
|
|
+ LA_KEY_NUMMULT, // AKEYCODE_NUMPAD_MULTIPLY
|
|
|
+ LA_KEY_NUMMINUS, // AKEYCODE_NUMPAD_SUBTRACT
|
|
|
+ LA_KEY_NUMPLUS, // AKEYCODE_NUMPAD_ADD
|
|
|
+ LA_KEY_NUMDOT, // AKEYCODE_NUMPAD_DOT
|
|
|
+ 0, // AKEYCODE_NUMPAD_COMMA
|
|
|
+ LA_KEY_NUMENTER, // AKEYCODE_NUMPAD_ENTER
|
|
|
+ '=' // AKEYCODE_NUMPAD_EQUALS
|
|
|
+};
|
|
|
+
|
|
|
static int32_t la_AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|
|
{
|
|
|
__android_log_print(ANDROID_LOG_DEBUG, "huh 5678", "123 input");
|
|
@@ -8241,7 +8434,46 @@ static int32_t la_AndroidInputCallback(struct android_app *app, AInputEvent *eve
|
|
|
|
|
|
int type = AInputEvent_getType(event);
|
|
|
if(type == AINPUT_EVENT_TYPE_KEY){
|
|
|
+ int32_t keycode = AKeyEvent_getKeyCode(event);
|
|
|
+ //int32_t AKeyEvent_getMetaState(event);
|
|
|
+ int key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE) ? KeycodeMap[keycode] : 0;
|
|
|
+ if (key != 0){
|
|
|
+ // Save current key and its state
|
|
|
+ // NOTE: Android key action is 0 for down and 1 for up
|
|
|
+ if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN){
|
|
|
+ la_SendKeyboardEvent(0,LA_KEY_DOWN,key);
|
|
|
+ if(key!=LA_KEY_BACKSPACE)
|
|
|
+ la_SendInputEvent(0,key);
|
|
|
+ }
|
|
|
+ else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_MULTIPLE){
|
|
|
+ la_SendKeyboardEvent(0,LA_KEY_DOWN,key);
|
|
|
+ la_SendInputEvent(0,key);
|
|
|
+ }
|
|
|
+ else la_SendKeyboardEvent(0,LA_KEY_UP,key); // Key up
|
|
|
+ }
|
|
|
+
|
|
|
+ if (keycode == AKEYCODE_POWER)
|
|
|
+ {
|
|
|
+ // Let the OS handle input to avoid app stuck. Behaviour: CMD_PAUSE -> CMD_SAVE_STATE -> CMD_STOP -> CMD_CONFIG_CHANGED -> CMD_LOST_FOCUS
|
|
|
+ // Resuming Behaviour: CMD_START -> CMD_RESUME -> CMD_CONFIG_CHANGED -> CMD_CONFIG_CHANGED -> CMD_GAINED_FOCUS
|
|
|
+ // It seems like locking mobile, screen size (CMD_CONFIG_CHANGED) is affected.
|
|
|
+ // NOTE: AndroidManifest.xml must have <activity android:configChanges="orientation|keyboardHidden|screenSize" >
|
|
|
+ // Before that change, activity was calling CMD_TERM_WINDOW and CMD_DESTROY when locking mobile, so that was not a normal behaviour
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ else if ((keycode == AKEYCODE_BACK) || (keycode == AKEYCODE_MENU))
|
|
|
+ {
|
|
|
+ // Eat BACK_BUTTON and AKEYCODE_MENU, just do nothing... and don't let to be handled by OS!
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ else if ((keycode == AKEYCODE_VOLUME_UP) || (keycode == AKEYCODE_VOLUME_DOWN))
|
|
|
+ {
|
|
|
+ // Set default OS behaviour
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
+
|
|
|
}
|
|
|
elif(type == AINPUT_EVENT_TYPE_MOTION){
|
|
|
int pcount = AMotionEvent_getPointerCount(event); int x,y;
|
|
@@ -8277,9 +8509,10 @@ static int32_t la_AndroidInputCallback(struct android_app *app, AInputEvent *eve
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void la_InitAssetManager(AAssetManager *manager, const char *dataPath){
|
|
|
+void la_InitAssetManager(AAssetManager *manager, const char *dataPath, const char *externalDataPath){
|
|
|
MAIN.AssetManager = manager;
|
|
|
MAIN.InternalDataPath = dataPath;
|
|
|
+ MAIN.ExternalDataPath = externalDataPath;
|
|
|
}
|
|
|
|
|
|
static int android_read(void *cookie, char *data, int dataSize){
|
|
@@ -8311,7 +8544,10 @@ FILE *android_fopen(const char *fileName, const char *mode)
|
|
|
// write data when required using the standard stdio FILE access functions
|
|
|
// Ref: https://stackoverflow.com/questions/11294487/android-writing-saving-files-from-native-code-only
|
|
|
#undef fopen
|
|
|
+ FILE* result=fopen(fileName, mode); if(result){ return result; }
|
|
|
sprintf(buf,"%s/%s", MAIN.InternalDataPath, fileName);
|
|
|
+ result=fopen(buf, mode); if(result) return result;
|
|
|
+ sprintf(buf,"%s/%s", MAIN.ExternalDataPath, fileName);
|
|
|
return fopen(buf, mode);
|
|
|
#define fopen(name, mode) android_fopen(name, mode)
|
|
|
}
|
|
@@ -8328,23 +8564,57 @@ FILE *android_fopen(const char *fileName, const char *mode)
|
|
|
else
|
|
|
{
|
|
|
#undef fopen
|
|
|
+ FILE* result=fopen(fileName, mode); if(result){ return result; }
|
|
|
// Just do a regular open if file is not found in the assets
|
|
|
sprintf(buf,"%s/%s", MAIN.InternalDataPath, fileName);
|
|
|
+ result=fopen(buf, mode); if(result){ return result; }
|
|
|
+ sprintf(buf,"%s/%s", MAIN.ExternalDataPath, fileName);
|
|
|
return fopen(buf, mode);
|
|
|
#define fopen(name, mode) android_fopen(name, mode)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void la_HideNavBar(){
|
|
|
+ JavaVM* lJavaVM = MAIN.app->activity->vm;
|
|
|
+ JNIEnv* lJNIEnv = MAIN.app->activity->env;
|
|
|
+ (*lJavaVM)->AttachCurrentThread(lJavaVM, &lJNIEnv,0);
|
|
|
+
|
|
|
+ jclass activityClass = (*lJNIEnv)->FindClass(lJNIEnv,"android/app/NativeActivity");
|
|
|
+ jmethodID getWindow = (*lJNIEnv)->GetMethodID(lJNIEnv,activityClass, "getWindow", "()Landroid/view/Window;");
|
|
|
+
|
|
|
+ jclass windowClass = (*lJNIEnv)->FindClass(lJNIEnv,"android/view/Window");
|
|
|
+ jmethodID getDecorView = (*lJNIEnv)->GetMethodID(lJNIEnv,windowClass, "getDecorView", "()Landroid/view/View;");
|
|
|
+
|
|
|
+ jclass viewClass = (*lJNIEnv)->FindClass(lJNIEnv,"android/view/View");
|
|
|
+ jmethodID setSystemUiVisibility = (*lJNIEnv)->GetMethodID(lJNIEnv,viewClass, "setSystemUiVisibility", "(I)V");
|
|
|
+
|
|
|
+ jobject window = (*lJNIEnv)->CallObjectMethod(lJNIEnv,MAIN.app->activity->clazz, getWindow);
|
|
|
+
|
|
|
+ jobject decorView = (*lJNIEnv)->CallObjectMethod(lJNIEnv,window, getDecorView);
|
|
|
+
|
|
|
+ jfieldID flagFullscreenID = (*lJNIEnv)->GetStaticFieldID(lJNIEnv,viewClass, "SYSTEM_UI_FLAG_FULLSCREEN", "I");
|
|
|
+ jfieldID flagHideNavigationID = (*lJNIEnv)->GetStaticFieldID(lJNIEnv,viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION", "I");
|
|
|
+
|
|
|
+ int flagFullscreen = (*lJNIEnv)->GetStaticIntField(lJNIEnv,viewClass, flagFullscreenID);
|
|
|
+ int flagHideNavigation = (*lJNIEnv)->GetStaticIntField(lJNIEnv,viewClass, flagHideNavigationID);
|
|
|
+
|
|
|
+ int flag = flagFullscreen | flagHideNavigation;
|
|
|
+
|
|
|
+ (*lJNIEnv)->CallVoidMethod(lJNIEnv,decorView, setSystemUiVisibility, flag);
|
|
|
+ (*lJavaVM)->DetachCurrentThread(lJavaVM);
|
|
|
+}
|
|
|
+
|
|
|
void la_InitAndroidPlatform(struct android_app *app){
|
|
|
MAIN.app=app;
|
|
|
|
|
|
- ANativeActivity_setWindowFlags(MAIN.app->activity, AWINDOW_FLAG_FULLSCREEN, 1); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
|
|
+ ANativeActivity_setWindowFlags(MAIN.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
|
|
+ //la_HideNavBar();
|
|
|
|
|
|
MAIN.app->onAppCmd = la_AndroidCommandCallback;
|
|
|
MAIN.app->onInputEvent = la_AndroidInputCallback;
|
|
|
|
|
|
- la_InitAssetManager(MAIN.app->activity->assetManager, MAIN.app->activity->internalDataPath);
|
|
|
+ la_InitAssetManager(MAIN.app->activity->assetManager, MAIN.app->activity->internalDataPath, MAIN.app->activity->externalDataPath);
|
|
|
|
|
|
int pollResult = 0;
|
|
|
int pollEvents = 0;
|
|
@@ -8380,5 +8650,99 @@ void android_main(struct android_app *app){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void la_DisplayKeyboard(bool pShow) {
|
|
|
+ // Attaches the current thread to the JVM.
|
|
|
+ jint lResult;
|
|
|
+ jint lFlags = 0;
|
|
|
+
|
|
|
+ JavaVM* lJavaVM = MAIN.app->activity->vm;
|
|
|
+ JNIEnv* lJNIEnv = MAIN.app->activity->env;
|
|
|
+
|
|
|
+ JavaVMAttachArgs lJavaVMAttachArgs;
|
|
|
+ lJavaVMAttachArgs.version = JNI_VERSION_1_6;
|
|
|
+ lJavaVMAttachArgs.name = "NativeThread";
|
|
|
+ lJavaVMAttachArgs.group = NULL;
|
|
|
+
|
|
|
+ lResult=(*lJavaVM)->AttachCurrentThread(lJavaVM, &lJNIEnv,0);
|
|
|
+ if (lResult == JNI_ERR) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // Retrieves NativeActivity.
|
|
|
+ jobject lNativeActivity = MAIN.app->activity->clazz;
|
|
|
+ jclass ClassNativeActivity = (*lJNIEnv)->GetObjectClass(lJNIEnv,lNativeActivity);
|
|
|
+ logPrintNew("jvm3");
|
|
|
+
|
|
|
+ // Retrieves Context.INPUT_METHOD_SERVICE.
|
|
|
+ jclass ClassContext = (*lJNIEnv)->FindClass(lJNIEnv,"android/content/Context");
|
|
|
+ jfieldID FieldINPUT_METHOD_SERVICE =
|
|
|
+ (*lJNIEnv)->GetStaticFieldID(lJNIEnv,ClassContext,
|
|
|
+ "INPUT_METHOD_SERVICE", "Ljava/lang/String;");
|
|
|
+ jobject INPUT_METHOD_SERVICE =
|
|
|
+ (*lJNIEnv)->GetStaticObjectField(lJNIEnv,ClassContext,
|
|
|
+ FieldINPUT_METHOD_SERVICE);
|
|
|
+ //jniCheck(INPUT_METHOD_SERVICE);
|
|
|
+ logPrintNew("jvm4");
|
|
|
+
|
|
|
+ // Runs getSystemService(Context.INPUT_METHOD_SERVICE).
|
|
|
+ jclass ClassInputMethodManager = (*lJNIEnv)->FindClass(lJNIEnv,
|
|
|
+ "android/view/inputmethod/InputMethodManager");
|
|
|
+ jmethodID MethodGetSystemService = (*lJNIEnv)->GetMethodID(lJNIEnv,
|
|
|
+ ClassNativeActivity, "getSystemService",
|
|
|
+ "(Ljava/lang/String;)Ljava/lang/Object;");
|
|
|
+ jobject lInputMethodManager = (*lJNIEnv)->CallObjectMethod(lJNIEnv,
|
|
|
+ lNativeActivity, MethodGetSystemService,
|
|
|
+ INPUT_METHOD_SERVICE);
|
|
|
+
|
|
|
+ // Runs getWindow().getDecorView().
|
|
|
+ jmethodID MethodGetWindow = (*lJNIEnv)->GetMethodID(lJNIEnv,
|
|
|
+ ClassNativeActivity, "getWindow",
|
|
|
+ "()Landroid/view/Window;");
|
|
|
+ jobject lWindow = (*lJNIEnv)->CallObjectMethod(lJNIEnv,lNativeActivity,
|
|
|
+ MethodGetWindow);
|
|
|
+ jclass ClassWindow = (*lJNIEnv)->FindClass(lJNIEnv,
|
|
|
+ "android/view/Window");
|
|
|
+ jmethodID MethodGetDecorView = (*lJNIEnv)->GetMethodID(lJNIEnv,
|
|
|
+ ClassWindow, "getDecorView", "()Landroid/view/View;");
|
|
|
+ jobject lDecorView = (*lJNIEnv)->CallObjectMethod(lJNIEnv,lWindow,
|
|
|
+ MethodGetDecorView);
|
|
|
+
|
|
|
+ if (pShow) {
|
|
|
+ // Runs lInputMethodManager.showSoftInput(...).
|
|
|
+ jmethodID MethodShowSoftInput = (*lJNIEnv)->GetMethodID(lJNIEnv,
|
|
|
+ ClassInputMethodManager, "showSoftInput",
|
|
|
+ "(Landroid/view/View;I)Z");
|
|
|
+ jboolean lResult = (*lJNIEnv)->CallBooleanMethod(lJNIEnv,
|
|
|
+ lInputMethodManager, MethodShowSoftInput,
|
|
|
+ lDecorView, lFlags);
|
|
|
+ } else {
|
|
|
+ // Runs lWindow.getViewToken()
|
|
|
+ jclass ClassView = (*lJNIEnv)->FindClass(lJNIEnv,
|
|
|
+ "android/view/View");
|
|
|
+ jmethodID MethodGetWindowToken = (*lJNIEnv)->GetMethodID(lJNIEnv,
|
|
|
+ ClassView, "getWindowToken", "()Landroid/os/IBinder;");
|
|
|
+ jobject lBinder = (*lJNIEnv)->CallObjectMethod(lJNIEnv,lDecorView,
|
|
|
+ MethodGetWindowToken);
|
|
|
+
|
|
|
+ // lInputMethodManager.hideSoftInput(...).
|
|
|
+ jmethodID MethodHideSoftInput = (*lJNIEnv)->GetMethodID(lJNIEnv,
|
|
|
+ ClassInputMethodManager, "hideSoftInputFromWindow",
|
|
|
+ "(Landroid/os/IBinder;I)Z");
|
|
|
+ jboolean lRes = (*lJNIEnv)->CallBooleanMethod(lJNIEnv,
|
|
|
+ lInputMethodManager, MethodHideSoftInput,
|
|
|
+ lBinder, lFlags);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Finished with the JVM.
|
|
|
+ (*lJavaVM)->DetachCurrentThread(lJavaVM);
|
|
|
+}
|
|
|
+
|
|
|
#endif //android
|
|
|
|
|
|
+#ifndef LAGUI_ANDROID
|
|
|
+void la_DisplayKeyboard(bool pShow) {
|
|
|
+ return;
|
|
|
+}
|
|
|
+void la_HideNavBar(){
|
|
|
+ return;
|
|
|
+}
|
|
|
+#endif
|