Android: more cleanup. Trying to solve the problem of undefined screen buffer content. Moved gradlew.bat into gradlew.zip to make some svn's happy.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12709 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2018-03-05 21:26:51 +00:00
parent 900457f0b4
commit 8c51282770
11 changed files with 140 additions and 152 deletions

View File

@ -15,6 +15,10 @@ Getting Started
1. Open the AndroidStudio project by loading the HelloAndroid directory.
1. Click *Run/Run 'app'*.
Micrososft Windows Users
------------------------
The file 'gradlew.zip' must be unzipped before you can use AndroidStudio. It contains the required file 'gradlew.bat'. This was neccessary because some svn setups block anything that looks like an executable file, including files that end in .bat .
Support
-------
If you've found an error in these samples, please [file an issue](http://www.fltk.org/str.php). Patches are encouraged, and may be submitted via the same FLTK Bug & Feature system.

View File

@ -21,7 +21,7 @@
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Enumerations.H>
Fl_Window *win;
Fl_Button *btn;
@ -52,29 +52,14 @@ struct engine {
struct engine engine = { 0 };
ANativeWindow_Buffer* gAGraphicsBuffer = 0;
static int64_t start_ms;
static void engine_draw_frame()
{
if (Fl_Android_Application::get_native_window() == NULL) {
// No window.
return;
}
ANativeWindow_Buffer buffer;
if (ANativeWindow_lock(Fl_Android_Application::get_native_window(), &buffer, NULL) < 0) {
LOGW("Unable to lock window buffer");
return;
}
gAGraphicsBuffer = &buffer;
//if (Fl_Android_Application::lock_screen()) {
Fl::damage(FL_DAMAGE_ALL);
win->redraw();
Fl::flush();
ANativeWindow_unlockAndPost(Fl_Android_Application::get_native_window());
gAGraphicsBuffer = 0L;
// Fl_Android_Application::unlock_and_post_screen();
//}
}
static void engine_term_display() {
@ -84,8 +69,8 @@ static void engine_term_display() {
static int32_t engine_handle_input(AInputEvent* event) {
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
engine.animating = 1;
Fl::e_x = Fl::e_x_root = AMotionEvent_getX(event, 0) * 600 / ANativeWindow_getWidth(Fl_Android_Application::get_native_window());
Fl::e_y = Fl::e_y_root = AMotionEvent_getY(event, 0) * 800 / ANativeWindow_getHeight(Fl_Android_Application::get_native_window());
Fl::e_x = Fl::e_x_root = AMotionEvent_getX(event, 0) * 600 / ANativeWindow_getWidth(Fl_Android_Application::native_window());
Fl::e_y = Fl::e_y_root = AMotionEvent_getY(event, 0) * 800 / ANativeWindow_getHeight(Fl_Android_Application::native_window());
Fl::e_state = FL_BUTTON1;
Fl::e_keysym = FL_Button+1;
if (AMotionEvent_getAction(event)==AMOTION_EVENT_ACTION_DOWN) {
@ -113,10 +98,10 @@ static void engine_handle_cmd(int32_t cmd) {
static int32_t format = WINDOW_FORMAT_RGB_565;
switch (cmd) {
case APP_CMD_INIT_WINDOW:
if (Fl_Android_Application::get_native_window() != NULL) {
if (Fl_Android_Application::native_window() != NULL) {
// fill_plasma() assumes 565 format, get it here
format = ANativeWindow_getFormat(Fl_Android_Application::get_native_window());
ANativeWindow_setBuffersGeometry(Fl_Android_Application::get_native_window(),
format = ANativeWindow_getFormat(Fl_Android_Application::native_window());
ANativeWindow_setBuffersGeometry(Fl_Android_Application::native_window(),
#if 1
600, //ANativeWindow_getWidth(app->window),
800, //ANativeWindow_getHeight(app->window),
@ -130,7 +115,7 @@ static void engine_handle_cmd(int32_t cmd) {
break;
case APP_CMD_TERM_WINDOW:
engine_term_display();
ANativeWindow_setBuffersGeometry(Fl_Android_Application::get_native_window(),
ANativeWindow_setBuffersGeometry(Fl_Android_Application::native_window(),
#if 1
600, //ANativeWindow_getWidth(app->window),
800, //ANativeWindow_getHeight(app->window),
@ -157,12 +142,9 @@ int main(int argc, char **argv)
Fl_Android_Application::set_on_app_cmd(engine_handle_cmd);
Fl_Android_Application::set_on_input_event(engine_handle_input);
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
start_ms = (((int64_t)now.tv_sec)*1000000000LL + now.tv_nsec)/1000000;
win = new Fl_Window(10, 10, 600, 400, "Hallo");
btn = new Fl_Button(190, 200, 280, 35, "Hello, Android!");
btn->color(FL_LIGHT2);
win->show();
@ -192,6 +174,7 @@ int main(int argc, char **argv)
return 0;
}
}
//Fl::flush();
if (engine.animating) {
engine_draw_frame();

View File

@ -1,90 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

Binary file not shown.

View File

@ -120,11 +120,16 @@ public:
static void pre_exec_cmd(int8_t cmd);
static void post_exec_cmd(int8_t cmd);
static ANativeWindow *get_native_window() { return pNativeWindow; }
static inline ANativeWindow *native_window() { return pNativeWindow; }
static inline ANativeWindow_Buffer &graphics_buffer() { return pNativeWindowBuffer; }
static int destroy_requested() { return pDestroyRequested; }
static void set_on_app_cmd(void (*cmd)(int32_t cmd)) { pOnAppCmd = cmd; }
static void set_on_input_event(int32_t (*cmd)(AInputEvent* event)) { pOnInputEvent = cmd; }
static bool lock_screen();
static void unlock_and_post_screen();
static bool screen_is_locked();
protected:
static void free_saved_state();
static void print_cur_config();
@ -134,12 +139,13 @@ protected:
static void* thread_entry(void* param);
static ANativeActivity *pActivity;
static AConfiguration* pConfig;
static void* pSavedState;
static AConfiguration *pConfig;
static void *pSavedState;
static size_t pSavedStateSize;
static ALooper* pLooper;
static AInputQueue* pInputQueue;
static ANativeWindow* pNativeWindow;
static ALooper *pLooper;
static AInputQueue *pInputQueue;
static ANativeWindow *pNativeWindow;
static ANativeWindow_Buffer pNativeWindowBuffer;
static int pActivityState;
static int pDestroyRequested;
static void (*pOnAppCmd)(int32_t cmd);

View File

@ -68,6 +68,9 @@ AInputQueue* Fl_Android_Application::pInputQueue = 0;
// When non-NULL, this is the window surface that the app can draw in.
ANativeWindow* Fl_Android_Application::pNativeWindow = 0;
// Use this buffer for direct drawing access
ANativeWindow_Buffer Fl_Android_Application::pNativeWindowBuffer = { 0 };
// Current state of the app's activity. May be either APP_CMD_START,
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
int Fl_Android_Application::pActivityState = 0;
@ -314,7 +317,7 @@ void Fl_Android_Application::process_input(struct android_poll_source* source)
{
AInputEvent* event = NULL;
while (AInputQueue_getEvent(pInputQueue, &event) >= 0) {
LOGV("New input event: type=%d\n", AInputEvent_getType(event));
//LOGV("New input event: type=%d\n", AInputEvent_getType(event));
if (AInputQueue_preDispatchEvent(pInputQueue, event)) {
continue;
}
@ -363,6 +366,76 @@ void *Fl_Android_Application::thread_entry(void* param)
return NULL;
}
/**
* Take ownership of screen memory for gaining write access.
*
* If the screen is already locked, it will not be locked again
* and a value of true will be returned.
*
* @return true if we gaines access, false if no access was granted and screen memory must not be writte to
*/
bool Fl_Android_Application::lock_screen()
{
if (screen_is_locked())
return true;
// TODO: or should we wait until the window is mapped?
// TODO: see also Fl_Window_Driver::wait_for_expose_value
if (!pNativeWindow) {
log_w("Unable to lock window buffer: no native window found.");
return false;
}
// 190, 200, 280, 35
ARect dirty = { .left=190, .top = 200, .right = 290, .bottom = 235 };
if (ANativeWindow_lock(pNativeWindow, &pNativeWindowBuffer, &dirty) < 0) {
log_w("Unable to lock window buffer: Android won't lock.");
return false;
}
log_w("Dirty rect is %d %d %d %d", dirty.left, dirty.top, dirty.right, dirty.bottom);
ANativeWindow_Buffer buf;
if (ANativeWindow_lock(pNativeWindow, &buf, &dirty) < 0) {
log_w("Unable to lock 2nd window buffer: Android won't lock.");
return false;
}
return true;
}
#include <FL/fl_draw.H>
/**
* Release screen memory ownership and give it back to the system.
*
* The memory content will be copied to the physical screen next.
* If the screen is not locked, this call will have no effect.
*/
void Fl_Android_Application::unlock_and_post_screen()
{
if (!screen_is_locked())
return;
static int i = 0;
fl_color( (i&1) ? FL_RED : FL_GREEN);
fl_rectf(i*10, 700, 50, 50);
i++;
if (i>10) i = 0;
ANativeWindow_unlockAndPost(pNativeWindow);
pNativeWindowBuffer.bits = 0L; // avoid any misunderstandings...
}
/**
* Is the screen currently locked?
* @return true if it is locked and the app has write access.
*/
bool Fl_Android_Application::screen_is_locked()
{
return (pNativeWindowBuffer.bits!=0L);
}
// --------------------------------------------------------------------
// Native activity interaction (called from main thread)
// --------------------------------------------------------------------

View File

@ -27,8 +27,6 @@
#include "Fl_Android_Screen_Driver.H"
#include <android/log.h>
extern ANativeWindow_Buffer* gAGraphicsBuffer;
#define LOG_TAG "FLTK"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
@ -71,14 +69,14 @@ void Fl_Android_Graphics_Driver::rectf_unscaled(float x, float y, float w, float
// TODo: clip the rectangle to all parts of the current clipping region
uint16_t cc = make565(color());
uint32_t ss = gAGraphicsBuffer->stride;
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
uint32_t ss = Fl_Android_Application::graphics_buffer().stride;
uint16_t *bits = (uint16_t*)Fl_Android_Application::graphics_buffer().bits;
uint32_t xx = (uint32_t)x;
uint32_t yy = (uint32_t)y;
uint32_t ww = (uint32_t)w;
uint32_t hh = (uint32_t)h;
for (uint32_t iy = yy; iy<hh; ++iy) {
uint16_t *d = bits + iy*ss + xx;
for (uint32_t iy = 0; iy<hh; ++iy) {
uint16_t *d = bits + (iy+yy)*ss + xx;
for (uint32_t ix = ww; ix>0; --ix) {
*d++ = cc;
}
@ -95,8 +93,8 @@ void Fl_Android_Graphics_Driver::xyline_unscaled(float x, float y, float x1)
w = x-x1;
x = x1;
}
uint32_t ss = gAGraphicsBuffer->stride;
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
uint32_t ss = Fl_Android_Application::graphics_buffer().stride;
uint16_t *bits = (uint16_t*)Fl_Android_Application::graphics_buffer().bits;
uint32_t xx = (uint32_t)x;
uint32_t yy = (uint32_t)y;
uint32_t ww = (uint32_t)w;
@ -116,8 +114,8 @@ void Fl_Android_Graphics_Driver::yxline_unscaled(float x, float y, float y1)
h = y-y1;
y = y1;
}
uint32_t ss = gAGraphicsBuffer->stride;
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
uint32_t ss = Fl_Android_Application::graphics_buffer().stride;
uint16_t *bits = (uint16_t*)Fl_Android_Application::graphics_buffer().bits;
uint32_t xx = (uint32_t)x;
uint32_t yy = (uint32_t)y;
uint32_t hh = (uint32_t)h;
@ -144,7 +142,7 @@ static int render_letter(int xx, int yy, uint32_t c)
int w,h,i,j, size = 30;
int dx, dy;
LOGE("Render letter %c", c);
//LOGE("Render letter %c", c);
if (once==0) {
once = 1;
FILE *f = fopen("/system/fonts/DroidSans.ttf", "rb");
@ -186,8 +184,8 @@ if (once==0) {
// rrrr.rggg.gggb.bbbb
xx += dx; yy += dy;
uint16_t cc = make565(fl_color()), cc12 = (cc&0xf7de)>>1, cc14 = (cc12&0xf7de)>>1, cc34 = cc12+cc14;
uint32_t ss = gAGraphicsBuffer->stride;
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
uint32_t ss = Fl_Android_Application::graphics_buffer().stride;
uint16_t *bits = (uint16_t*)Fl_Android_Application::graphics_buffer().bits;
uint32_t ww = w;
uint32_t hh = h;
unsigned char *s = bitmap;

View File

@ -79,8 +79,8 @@ public:
// --- audible output
virtual void beep(int type);
// --- global events
virtual void flush();
#endif
virtual void flush();
virtual double wait(double time_to_wait);
#if 0
virtual int ready();

View File

@ -19,6 +19,7 @@
#include "../../config_lib.h"
#include "Fl_Android_Screen_Driver.H"
#include "Fl_Android_Application.H"
#include "./Fl_Font.H"
#include <FL/Fl.H>
#include <FL/platform.H>
@ -27,13 +28,6 @@
#include <FL/fl_ask.H>
#include <stdio.h>
#include <android/log.h>
#define LOG_TAG "FLTK"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOGV(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
static void nothing() {}
void (*fl_unlock_function)() = nothing;
@ -375,14 +369,24 @@ void Fl_WinAPI_Screen_Driver::beep(int type)
break;
}
}
#endif
void Fl_WinAPI_Screen_Driver::flush()
/**
* On Android, get access to screen memory, then flush(), then
* release screen memory and post it to the physicla screen.
*
* Don't do anything if the screen wasn't previously locked by
* any Fl_Window_Driver. We would just needlessly repost the same screen.
*/
void Fl_Android_Screen_Driver::flush()
{
GdiFlush();
if (Fl_Android_Application::screen_is_locked()) {
Fl_Screen_Driver::flush();
Fl_Android_Application::unlock_and_post_screen();
}
}
#if 0
extern void fl_fix_focus(); // in Fl.cxx
// We have to keep track of whether we have captured the mouse, since

View File

@ -103,8 +103,8 @@ public:
virtual void flush_double();
virtual void flush_overlay();
virtual void draw_begin();
virtual void make_current() { sCurrent = this; }
#endif
virtual void make_current();
virtual void show();
#if 0
virtual void label(const char *name,const char *iname);
@ -134,6 +134,8 @@ public:
#endif
// Leuwer: 0171 473 1850
};

View File

@ -29,6 +29,7 @@
#include "Fl_Android_Window_Driver.H"
#include "Fl_Android_Screen_Driver.H"
#include "Fl_Android_Graphics_Driver.H"
#include "Fl_Android_Application.H"
#if 0
@ -73,6 +74,13 @@ void Fl_Android_Window_Driver::show()
}
}
void Fl_Android_Window_Driver::make_current()
{
Fl_Android_Application::lock_screen();
}
#if 0
Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win)