From b1d5bdbb8c5643e1ae40bdf92d2deda352f27eb5 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 29 Jan 2019 16:35:23 +0100 Subject: [PATCH] fix android view resize on keyboard, also allow all device orientations --- android/src/main/AndroidManifest.xml | 6 +- android/src/main/cpp/main.cpp | 96 ++++++++++++++----- .../com/omixlab/panopainter/MainActivity.java | 20 ++++ src/app.cpp | 7 +- src/app.h | 2 + src/node_canvas.cpp | 2 +- src/node_viewport.cpp | 3 +- 7 files changed, 105 insertions(+), 31 deletions(-) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 17b41a8..c4b38a3 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,8 +1,6 @@ + package="com.omixlab.panopainter"> @@ -13,7 +11,7 @@ diff --git a/android/src/main/cpp/main.cpp b/android/src/main/cpp/main.cpp index 902c50e..aa91f35 100755 --- a/android/src/main/cpp/main.cpp +++ b/android/src/main/cpp/main.cpp @@ -54,6 +54,7 @@ EGLDisplay g_display = EGL_NO_DISPLAY; EGLContext g_context = EGL_NO_CONTEXT; std::recursive_mutex mutex; int mutex_count = 0; +struct engine g_engine; jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) { @@ -276,6 +277,20 @@ JNIEXPORT void JNICALL Java_com_omixlab_panopainter_MainActivity_pickExternalCal App::I.data_path = file_path; App::I.work_path = file_path; } +JNIEXPORT void JNICALL Java_com_omixlab_panopainter_MainActivity_contentRectChanged(JNIEnv *end, jobject, + jint wnd_w, jint wnd_h, jint rect_left, jint rect_top, jint rect_right, jint rect_bottom) +{ + LOG("resize wnd [%d %d] rect [%d %d %d %d]", wnd_w, wnd_h, rect_left, rect_top, rect_right, rect_bottom); + locker _lock(&g_engine); + App::I.width = wnd_w; + App::I.height = (rect_bottom - rect_top); + App::I.off_x = 0; + App::I.off_y = wnd_h - (rect_bottom - rect_top); + App::I.redraw = true; + //App::I.resize(App::I.width, App::I.height); + g_engine.width = wnd_w; + g_engine.height = wnd_h; +} } void android_pick_file(android_app* mApplication, std::function callback) @@ -670,6 +685,24 @@ static int engine_init_display(struct engine* engine) { */ static void engine_draw_frame(struct engine* engine) { locker _lock(engine); + + /* + if (engine->display == NULL) + return; + + int w, h; + eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w); + eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h); + + if (w != engine->width || h != engine->height) { + engine->width = w; + engine->height = h; + App::I.resize(w, h); + App::I.redraw = true; + LOG("resize window to %d %d", w, h); + } + */ + if (engine->display == NULL || !(App::I.redraw || App::I.animate)) return; @@ -895,6 +928,7 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) { case APP_CMD_RESUME: LOG("APP_CMD_RESUME"); App::I.redraw = true; + ALooper_wake(engine->app->looper); break; case APP_CMD_SAVE_STATE: // The system has asked us to save our current state. Do so. @@ -939,6 +973,23 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) { engine->animating = 0; engine_draw_frame(engine); break; + case APP_CMD_WINDOW_REDRAW_NEEDED: + LOG("APP_CMD_WINDOW_REDRAW_NEEDED"); + App::I.redraw = true; + ALooper_wake(engine->app->looper); + break; + case APP_CMD_WINDOW_RESIZED: + LOG("APP_CMD_WINDOW_RESIZED"); + App::I.redraw = true; + ALooper_wake(engine->app->looper); + break; + case APP_CMD_CONTENT_RECT_CHANGED: + LOG("APP_CMD_CONTENT_RECT_CHANGED"); + //App::I.width = engine->app->contentRect.right - engine->app->contentRect.left; + //App::I.height = engine->app->contentRect.bottom - engine->app->contentRect.top; + LOG("content rect %f %f", App::I.width, App::I.height); + ALooper_wake(engine->app->looper); + break; } } @@ -948,32 +999,28 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) { * event loop for receiving input events and doing other things. */ void android_main(struct android_app* state) { - struct engine engine; - // Make sure glue isn't stripped. // DON'T REMOVE, even if the compiler say it's deprecated app_dummy(); - memset(&engine, 0, sizeof(engine)); - state->userData = &engine; + memset(&g_engine, 0, sizeof(g_engine)); + state->userData = &g_engine; state->onAppCmd = engine_handle_cmd; state->onInputEvent = engine_handle_input; - engine.app = state; + g_engine.app = state; // Prepare to monitor accelerometer - engine.sensorManager = ASensorManager_getInstance(); - engine.accelerometerSensor = ASensorManager_getDefaultSensor( - engine.sensorManager, - ASENSOR_TYPE_ACCELEROMETER); - engine.sensorEventQueue = ASensorManager_createEventQueue( - engine.sensorManager, - state->looper, LOOPER_ID_USER, - NULL, NULL); - +/* + g_engine.sensorManager = ASensorManager_getInstance(); + g_engine.accelerometerSensor = ASensorManager_getDefaultSensor( + g_engine.sensorManager, ASENSOR_TYPE_ACCELEROMETER); + g_engine.sensorEventQueue = ASensorManager_createEventQueue( + g_engine.sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL); +*/ LOG("START MAIN"); if (state->savedState != NULL) { // We are starting with a previous saved state; restore from it. - engine.state = *(struct saved_state*)state->savedState; + g_engine.state = *(struct saved_state*)state->savedState; } //App::I.create(); @@ -991,8 +1038,8 @@ void android_main(struct android_app* state) { // If animating, we loop until all events are read, then continue // to draw the next frame of animation. bool used = false; - while (!used && (ident=ALooper_pollAll(-1, NULL, &events, - (void**)&source)) >= 0) { + while (!used && (ident=ALooper_pollOnce(100, NULL, &events, + (void**)&source)) != ALOOPER_POLL_ERROR) { // Process this event. if (source != NULL) { @@ -1002,9 +1049,9 @@ void android_main(struct android_app* state) { // If a sensor has data, process it now. if (ident == LOOPER_ID_USER) { - if (engine.accelerometerSensor != NULL) { + if (g_engine.accelerometerSensor != NULL) { ASensorEvent event; - while (ASensorEventQueue_getEvents(engine.sensorEventQueue, + while (ASensorEventQueue_getEvents(g_engine.sensorEventQueue, &event, 1) > 0) { // LOGI("accelerometer: x=%f y=%f z=%f", // event.acceleration.x, event.acceleration.y, @@ -1013,15 +1060,20 @@ void android_main(struct android_app* state) { } } + if (ident == ALOOPER_POLL_TIMEOUT || ident == ALOOPER_POLL_CALLBACK){ + App::I.redraw = true; + engine_draw_frame(&g_engine); + } + // Check if we are exiting. if (state->destroyRequested != 0) { - engine_term_display(&engine); + engine_term_display(&g_engine); return; } } //if (engine.animating) - if (engine.display != EGL_NO_DISPLAY) + if (g_engine.display != EGL_NO_DISPLAY) { if (pick_file_callback_context) { @@ -1031,7 +1083,7 @@ void android_main(struct android_app* state) { // Drawing is throttled to the screen update rate, so there // is no need to do timing here. - engine_draw_frame(&engine); + engine_draw_frame(&g_engine); } } } diff --git a/android/src/main/java/com/omixlab/panopainter/MainActivity.java b/android/src/main/java/com/omixlab/panopainter/MainActivity.java index c8e7734..7123306 100644 --- a/android/src/main/java/com/omixlab/panopainter/MainActivity.java +++ b/android/src/main/java/com/omixlab/panopainter/MainActivity.java @@ -5,10 +5,13 @@ import android.app.Activity; import android.app.NativeActivity; import android.content.Intent; import android.content.pm.PackageManager; +import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.util.Log; +import android.view.View; +import android.view.ViewTreeObserver; import java.io.File; import java.io.FileNotFoundException; @@ -26,10 +29,27 @@ public class MainActivity extends NativeActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); checkPermissionReadStorage(); + getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + + @Override + public void onGlobalLayout() { + + Rect r = new Rect(); + getWindow().getDecorView().getWindowVisibleDisplayFrame(r); + + int screenHeight = getWindow().getDecorView().getRootView().getHeight(); + int heightDifference = screenHeight - (r.bottom - r.top); + Log.d("Keyboard Size", "Size: " + heightDifference); + View rv = getWindow().getDecorView().getRootView(); + + contentRectChanged(rv.getWidth(), rv.getHeight(), r.left, r.top, r.right, r.bottom); + } + }); } public native void pickFileCallback(String path); public native void pickExternalCallback(String path); + public native void contentRectChanged(int wnd_w, int wnd_h, int rect_left, int rect_top, int rect_right, int rect_bottom); public void setRootPath() { diff --git a/src/app.cpp b/src/app.cpp index 69336eb..b09f852 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -97,7 +97,7 @@ bool App::request_close() void App::clear() { glClearColor(.1f, .1f, .1f, 1.f); - glViewport(0, 0, (GLsizei)width, (GLsizei)height); + glViewport(off_x, off_y, (GLsizei)width, (GLsizei)height); glClear(GL_COLOR_BUFFER_BIT); } @@ -500,12 +500,13 @@ void App::update(float dt) //auto box = n->m_clip; //glm::ivec4 c = glm::vec4((int)box.x - 1, (int)(height / zoom - box.y - box.w) - 1, (int)box.z + 2, (int)box.w + 2) * zoom; glm::ivec4 c = glm::vec4((int)box.x, (int)(height / zoom - box.y - box.w), (int)box.z, (int)box.w) * zoom; - glScissor(c.x, c.y, c.z, c.w); + glScissor(c.x + off_x, c.y + off_y, c.z, c.w); n->draw(); return true; } return false; }; + /* uirtt.bindFramebuffer(); uirtt.clear(); glEnable(GL_SCISSOR_TEST); @@ -514,7 +515,7 @@ void App::update(float dt) //msgbox->watch(observer); glDisable(GL_SCISSOR_TEST); uirtt.unbindFramebuffer(); - + */ #if __IOS__ [ios_view->glview bindDrawable]; #else diff --git a/src/app.h b/src/app.h index f55eb78..226fd36 100644 --- a/src/app.h +++ b/src/app.h @@ -79,6 +79,8 @@ public: std::string doc_filename; bool has_stylus = false; bool has_vr = false; + float off_x = 0; + float off_y = 0; float width; float height; bool keys[256]; diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index 7ccf554..f00ec01 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -70,7 +70,7 @@ void NodeCanvas::draw() glm::ivec4 c = (glm::ivec4)glm::vec4(box.x, (int)(vp[3] - box.y - box.w), box.z, box.w); glClearColor(1, 1, 1, 0); glClear(GL_COLOR_BUFFER_BIT); - glViewport(c.x, c.y, c.z, c.w); + glViewport(c.x + App::I.off_x, c.y + App::I.off_y, c.z, c.w); //m_canvas->m_cam_rot = m_pan * 0.003f; diff --git a/src/node_viewport.cpp b/src/node_viewport.cpp index 5a270e2..e58d515 100644 --- a/src/node_viewport.cpp +++ b/src/node_viewport.cpp @@ -2,6 +2,7 @@ #include "log.h" #include "node_viewport.h" #include "shader.h" +#include "app.h" void NodeViewport::draw() { @@ -17,7 +18,7 @@ void NodeViewport::draw() glClear(GL_COLOR_BUFFER_BIT); auto box = m_clip * root()->m_zoom; glm::ivec4 c = (glm::ivec4)glm::vec4(box.x, (int)(vp[3] - box.y - box.w), box.z, box.w); - glViewport(c.x, c.y, c.z, c.w); + glViewport(c.x + App::I.off_x, c.y + App::I.off_y, c.z, c.w); TextureManager::get(m_tex_id).bind(); m_sampler->bind(0); glEnable(GL_BLEND);