fix android view resize on keyboard, also allow all device orientations
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.omixlab.panopainter"
|
package="com.omixlab.panopainter">
|
||||||
android:versionCode="1"
|
|
||||||
android:versionName="1.0">
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
@@ -13,7 +11,7 @@
|
|||||||
<activity android:name=".MainActivity"
|
<activity android:name=".MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:screenOrientation="sensorLandscape"
|
android:screenOrientation="sensor"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<meta-data android:name="android.app.lib_name"
|
<meta-data android:name="android.app.lib_name"
|
||||||
android:value="native-lib" />
|
android:value="native-lib" />
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ EGLDisplay g_display = EGL_NO_DISPLAY;
|
|||||||
EGLContext g_context = EGL_NO_CONTEXT;
|
EGLContext g_context = EGL_NO_CONTEXT;
|
||||||
std::recursive_mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
int mutex_count = 0;
|
int mutex_count = 0;
|
||||||
|
struct engine g_engine;
|
||||||
|
|
||||||
jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
|
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.data_path = file_path;
|
||||||
App::I.work_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<void(std::string)> callback)
|
void android_pick_file(android_app* mApplication, std::function<void(std::string)> callback)
|
||||||
@@ -670,6 +685,24 @@ static int engine_init_display(struct engine* engine) {
|
|||||||
*/
|
*/
|
||||||
static void engine_draw_frame(struct engine* engine) {
|
static void engine_draw_frame(struct engine* engine) {
|
||||||
locker _lock(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))
|
if (engine->display == NULL || !(App::I.redraw || App::I.animate))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -895,6 +928,7 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
|
|||||||
case APP_CMD_RESUME:
|
case APP_CMD_RESUME:
|
||||||
LOG("APP_CMD_RESUME");
|
LOG("APP_CMD_RESUME");
|
||||||
App::I.redraw = true;
|
App::I.redraw = true;
|
||||||
|
ALooper_wake(engine->app->looper);
|
||||||
break;
|
break;
|
||||||
case APP_CMD_SAVE_STATE:
|
case APP_CMD_SAVE_STATE:
|
||||||
// The system has asked us to save our current state. Do so.
|
// 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->animating = 0;
|
||||||
engine_draw_frame(engine);
|
engine_draw_frame(engine);
|
||||||
break;
|
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.
|
* event loop for receiving input events and doing other things.
|
||||||
*/
|
*/
|
||||||
void android_main(struct android_app* state) {
|
void android_main(struct android_app* state) {
|
||||||
struct engine engine;
|
|
||||||
|
|
||||||
// Make sure glue isn't stripped.
|
// Make sure glue isn't stripped.
|
||||||
// DON'T REMOVE, even if the compiler say it's deprecated
|
// DON'T REMOVE, even if the compiler say it's deprecated
|
||||||
app_dummy();
|
app_dummy();
|
||||||
|
|
||||||
memset(&engine, 0, sizeof(engine));
|
memset(&g_engine, 0, sizeof(g_engine));
|
||||||
state->userData = &engine;
|
state->userData = &g_engine;
|
||||||
state->onAppCmd = engine_handle_cmd;
|
state->onAppCmd = engine_handle_cmd;
|
||||||
state->onInputEvent = engine_handle_input;
|
state->onInputEvent = engine_handle_input;
|
||||||
engine.app = state;
|
g_engine.app = state;
|
||||||
|
|
||||||
// Prepare to monitor accelerometer
|
// Prepare to monitor accelerometer
|
||||||
engine.sensorManager = ASensorManager_getInstance();
|
/*
|
||||||
engine.accelerometerSensor = ASensorManager_getDefaultSensor(
|
g_engine.sensorManager = ASensorManager_getInstance();
|
||||||
engine.sensorManager,
|
g_engine.accelerometerSensor = ASensorManager_getDefaultSensor(
|
||||||
ASENSOR_TYPE_ACCELEROMETER);
|
g_engine.sensorManager, ASENSOR_TYPE_ACCELEROMETER);
|
||||||
engine.sensorEventQueue = ASensorManager_createEventQueue(
|
g_engine.sensorEventQueue = ASensorManager_createEventQueue(
|
||||||
engine.sensorManager,
|
g_engine.sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL);
|
||||||
state->looper, LOOPER_ID_USER,
|
*/
|
||||||
NULL, NULL);
|
|
||||||
|
|
||||||
LOG("START MAIN");
|
LOG("START MAIN");
|
||||||
if (state->savedState != NULL) {
|
if (state->savedState != NULL) {
|
||||||
// We are starting with a previous saved state; restore from it.
|
// 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();
|
//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
|
// If animating, we loop until all events are read, then continue
|
||||||
// to draw the next frame of animation.
|
// to draw the next frame of animation.
|
||||||
bool used = false;
|
bool used = false;
|
||||||
while (!used && (ident=ALooper_pollAll(-1, NULL, &events,
|
while (!used && (ident=ALooper_pollOnce(100, NULL, &events,
|
||||||
(void**)&source)) >= 0) {
|
(void**)&source)) != ALOOPER_POLL_ERROR) {
|
||||||
|
|
||||||
// Process this event.
|
// Process this event.
|
||||||
if (source != NULL) {
|
if (source != NULL) {
|
||||||
@@ -1002,9 +1049,9 @@ void android_main(struct android_app* state) {
|
|||||||
|
|
||||||
// If a sensor has data, process it now.
|
// If a sensor has data, process it now.
|
||||||
if (ident == LOOPER_ID_USER) {
|
if (ident == LOOPER_ID_USER) {
|
||||||
if (engine.accelerometerSensor != NULL) {
|
if (g_engine.accelerometerSensor != NULL) {
|
||||||
ASensorEvent event;
|
ASensorEvent event;
|
||||||
while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
|
while (ASensorEventQueue_getEvents(g_engine.sensorEventQueue,
|
||||||
&event, 1) > 0) {
|
&event, 1) > 0) {
|
||||||
// LOGI("accelerometer: x=%f y=%f z=%f",
|
// LOGI("accelerometer: x=%f y=%f z=%f",
|
||||||
// event.acceleration.x, event.acceleration.y,
|
// 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.
|
// Check if we are exiting.
|
||||||
if (state->destroyRequested != 0) {
|
if (state->destroyRequested != 0) {
|
||||||
engine_term_display(&engine);
|
engine_term_display(&g_engine);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (engine.animating)
|
//if (engine.animating)
|
||||||
if (engine.display != EGL_NO_DISPLAY)
|
if (g_engine.display != EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
if (pick_file_callback_context)
|
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
|
// Drawing is throttled to the screen update rate, so there
|
||||||
// is no need to do timing here.
|
// is no need to do timing here.
|
||||||
engine_draw_frame(&engine);
|
engine_draw_frame(&g_engine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import android.app.Activity;
|
|||||||
import android.app.NativeActivity;
|
import android.app.NativeActivity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -26,10 +29,27 @@ public class MainActivity extends NativeActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
checkPermissionReadStorage();
|
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 pickFileCallback(String path);
|
||||||
public native void pickExternalCallback(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()
|
public void setRootPath()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ bool App::request_close()
|
|||||||
void App::clear()
|
void App::clear()
|
||||||
{
|
{
|
||||||
glClearColor(.1f, .1f, .1f, 1.f);
|
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);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,12 +500,13 @@ void App::update(float dt)
|
|||||||
//auto box = n->m_clip;
|
//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 - 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;
|
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();
|
n->draw();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
uirtt.bindFramebuffer();
|
uirtt.bindFramebuffer();
|
||||||
uirtt.clear();
|
uirtt.clear();
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
@@ -514,7 +515,7 @@ void App::update(float dt)
|
|||||||
//msgbox->watch(observer);
|
//msgbox->watch(observer);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
uirtt.unbindFramebuffer();
|
uirtt.unbindFramebuffer();
|
||||||
|
*/
|
||||||
#if __IOS__
|
#if __IOS__
|
||||||
[ios_view->glview bindDrawable];
|
[ios_view->glview bindDrawable];
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ public:
|
|||||||
std::string doc_filename;
|
std::string doc_filename;
|
||||||
bool has_stylus = false;
|
bool has_stylus = false;
|
||||||
bool has_vr = false;
|
bool has_vr = false;
|
||||||
|
float off_x = 0;
|
||||||
|
float off_y = 0;
|
||||||
float width;
|
float width;
|
||||||
float height;
|
float height;
|
||||||
bool keys[256];
|
bool keys[256];
|
||||||
|
|||||||
@@ -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);
|
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);
|
glClearColor(1, 1, 1, 0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
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;
|
//m_canvas->m_cam_rot = m_pan * 0.003f;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "node_viewport.h"
|
#include "node_viewport.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
void NodeViewport::draw()
|
void NodeViewport::draw()
|
||||||
{
|
{
|
||||||
@@ -17,7 +18,7 @@ void NodeViewport::draw()
|
|||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
auto box = m_clip * root()->m_zoom;
|
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);
|
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();
|
TextureManager::get(m_tex_id).bind();
|
||||||
m_sampler->bind(0);
|
m_sampler->bind(0);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
|||||||
Reference in New Issue
Block a user