+#define _Noreturn
+
namespace gui::drivers;
import "Window"
#include <locale.h>
#include <pthread.h>
#include <unistd.h>
+#include <sys/prctl.h>
#include <android/configuration.h>
#include <android/looper.h>
#undef set
#undef uint
+#define printf(...) ((void)__android_log_print(ANDROID_LOG_INFO, "ecere-app", __VA_ARGS__))
+
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "ecere-app", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "ecere-app", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "ecere-app", __VA_ARGS__))
-#ifdef _DEBUG
+#ifndef _DEBUG
#define LOGV(...) ((void)0)
#else
#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__))
virtual void any_object::process();
};
+static const char * packagePath;
+
class AndroidAppGlue : Thread
{
void* userData;
AInputEvent* event = null;
if(AInputQueue_getEvent(inputQueue, &event) >= 0)
{
- int handled = 0;
+ //int handled = 0;
LOGV("New input event: type=%d\n", AInputEvent_getType(event));
if(AInputQueue_preDispatchEvent(inputQueue, event))
return;
- handled = onInputEvent(event);
+ /*handled = */onInputEvent(event);
//AInputQueue_finishEvent(inputQueue, event, handled);
}
else
void pre_exec_cmd(AppCommand cmd)
{
- PrintLn("pre_exec_cmd: ", (int)cmd);
+ //PrintLn("pre_exec_cmd: ", cmd);
switch(cmd)
{
case inputChanged:
void post_exec_cmd(AppCommand cmd)
{
- PrintLn("post_exec_cmd: ", (int)cmd);
+ //PrintLn("post_exec_cmd: ", cmd);
switch(cmd)
{
case termWindow:
savedStateSize = 0;
}
- void Create()
+ public void Create()
{
int msgpipe[2];
if(pipe(msgpipe))
static void onDestroy(ANativeActivity* activity)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("Destroy: %p\n", activity);
+ LOGI("Destroy: %p\n", activity);
app.cleanup();
app.Wait();
delete androidActivity;
delete __androidCurrentModule;
- LOGV("THE END.");
+ LOGI("THE END.");
}
static void onStart(ANativeActivity* activity)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("Start: %p\n", activity);
+ LOGI("Start: %p\n", activity);
app.set_activity_state(start);
}
static void onResume(ANativeActivity* activity)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("Resume: %p\n", activity);
+ LOGI("Resume: %p\n", activity);
app.set_activity_state(resume);
}
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
void* savedState = null;
- LOGV("SaveInstanceState: %p\n", activity);
+ LOGI("SaveInstanceState: %p\n", activity);
app.mutex.Wait();
app.stateSaved = false;
app.write_cmd(saveState);
static void onPause(ANativeActivity* activity)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("Pause: %p\n", activity);
+ LOGI("Pause: %p\n", activity);
app.set_activity_state(pause);
}
static void onStop(ANativeActivity* activity)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("Stop: %p\n", activity);
+ LOGI("Stop: %p\n", activity);
app.set_activity_state(stop);
}
static void onConfigurationChanged(ANativeActivity* activity)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("ConfigurationChanged: %p\n", activity);
+ LOGI("ConfigurationChanged: %p\n", activity);
app.write_cmd(configChanged);
}
static void onLowMemory(ANativeActivity* activity)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("LowMemory: %p\n", activity);
+ LOGI("LowMemory: %p\n", activity);
app.write_cmd(lowMemory);
}
static void onWindowFocusChanged(ANativeActivity* activity, int focused)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
+ LOGI("WindowFocusChanged: %p -- %d\n", activity, focused);
app.write_cmd(focused ? gainedFocus : lostFocus);
}
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
+ LOGI("NativeWindowCreated: %p -- %p\n", activity, window);
app.set_window(window);
}
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
+ LOGI("NativeWindowDestroyed: %p -- %p\n", activity, window);
+ app.window = null;
app.set_window(null);
}
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
+ LOGI("InputQueueCreated: %p -- %p\n", activity, queue);
app.set_input(queue);
}
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
{
AndroidAppGlue app = (AndroidAppGlue)activity->instance;
- LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
+ LOGI("InputQueueDestroyed: %p -- %p\n", activity, queue);
app.inputQueue = null;
app.set_input(null);
}
__thisModule = null;
__androidCurrentModule = null;
- LOGV("Creating: %p\n", activity);
+ prctl(PR_SET_DUMPABLE, 1);
+
+ LOGI("Creating: %p\n", activity);
//(*activity->vm)->AttachCurrentThread(activity->vm, &env, 0);
clazz = (*env)->GetObjectClass(env, activity->clazz);
methodID = (*env)->GetMethodID(env, clazz, "getPackageName", "()Ljava/lang/String;");
result = (*env)->CallObjectMethod(env, activity->clazz, methodID);
str = (*env)->GetStringUTFChars(env, (jstring)result, &isCopy);
- // (*activity->vm)->DetachCurrentThread(activity->vm);
+
moduleName = strstr(str, "com.ecere.");
if(moduleName) moduleName += 10;
androidArgv[0] = moduleName;
+ methodID = (*env)->GetMethodID(env, clazz, "getPackageCodePath", "()Ljava/lang/String;");
+ result = (*env)->CallObjectMethod(env, activity->clazz, methodID);
+ str = (*env)->GetStringUTFChars(env, (jstring)result, &isCopy);
+ packagePath = str;
+ // (*activity->vm)->DetachCurrentThread(activity->vm);
+ LOGI("packagePath: %s\n", packagePath);
+
// Create a base Application class
__androidCurrentModule = __ecere_COM_Initialize(true, 1, androidArgv);
// Load up Ecere
eModule_Load(__androidCurrentModule, "ecere", publicAccess);
-
+ /*
if(activity->internalDataPath) PrintLn("internalDataPath is ", activity->internalDataPath);
if(activity->externalDataPath) PrintLn("externalDataPath is ", activity->externalDataPath);
{
char tmp[256];
PrintLn("cwd is ", GetWorkingDir(tmp, sizeof(tmp)));
}
+ */
ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN|AWINDOW_FLAG_KEEP_SCREEN_ON, 0 );
app = AndroidActivity { activity = activity, moduleName = moduleName };
+
incref app;
- app.setSavedState(savedState, savedStateSize);
+ app.setSavedState(savedState, (uint)savedStateSize);
activity->callbacks->onDestroy = onDestroy;
activity->callbacks->onStart = onStart;
activity->callbacks->onResume = onResume;
if(androidActivity.ident < 0)
androidActivity.ident = (LooperID)ALooper_pollAll(0, null, &androidActivity.events, (void**)&androidActivity.source);
+
+ if(gotInit && androidActivity.window)
+ {
+ int w = ANativeWindow_getWidth(androidActivity.window);
+ int h = ANativeWindow_getHeight(androidActivity.window);
+ if(desktopW != w || desktopH != h)
+ {
+ guiApp.SetDesktopPosition(0, 0, w, h, true);
+ desktopW = w;
+ desktopH = h;
+ guiApp.desktop.Update(null);
+ }
+ }
+
while(androidActivity.ident >= 0)
{
AndroidPollSource source = androidActivity.source;
}
}
*/
- if(gotInit && androidActivity.window)
- {
- int w = ANativeWindow_getWidth(androidActivity.window);
- int h = ANativeWindow_getHeight(androidActivity.window);
- if(desktopW != w || desktopH != h)
- {
- guiApp.SetDesktopPosition(0, 0, w, h, true);
- desktopW = w;
- desktopH = h;
- guiApp.desktop.Update(null);
- }
- }
eventAvailable = true;
if(androidActivity.destroyRequested)
}
- char ** GraphicsDrivers(int * numDrivers)
+ const char ** GraphicsDrivers(int * numDrivers)
{
- static char *graphicsDrivers[] = { "OpenGL" };
+ static const char *graphicsDrivers[] = { "OpenGL" };
*numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
- return (char **)graphicsDrivers;
+ return (const char **)graphicsDrivers;
}
void GetCurrentMode(bool * fullScreen, int * resolution, int * colorDepth, int * refreshRate)
// -- Window manipulation ---
- void SetRootWindowCaption(Window window, char * name)
+ void SetRootWindowCaption(Window window, const char * name)
{
}
void GetMousePosition(int *x, int *y)
{
- int rootWindow, childWindow;
- int mx, my;
- unsigned int state;
-
*x = mouseX;
*y = mouseY;
}
// -- Mouse cursor ---
- void SetMouseCursor(int cursor)
+ void SetMouseCursor(Window window, int cursor)
{
if(cursor == -1)
{
bool GetKeyState(Key key)
{
- int keyState = 0;
+ bool keyState = false;
return keyState;
}
static AndroidActivity androidActivity;
-default const char * AndroidInterface_GetLibLocation()
+default const char * AndroidInterface_GetLibLocation(Application a)
{
- if(androidActivity)
+ static char loc[MAX_LOCATION] = "", mod[MAX_LOCATION];
+ bool found = false;
+#if defined(__LP64__)
+ static const char * arch = "arm64";
+#else
+ static const char * arch = "armeabi";
+#endif
+ int i;
+ bool useArch = true;
+
+ while(!found)
{
- static char loc[MAX_LOCATION];
- sprintf(loc, "/data/data/com.ecere.%s/lib/lib", androidActivity.moduleName);
- return loc;
+ StripLastDirectory(packagePath, loc);
+ strcatf(loc, "/lib/%s/lib", useArch ? arch : "");
+ sprintf(mod, "%s%s.so", loc, a.argv[0]);
+ found = FileExists(mod).isFile;
+ if(!found)
+ {
+ bool useApp = true;
+ while(!found)
+ {
+ for(i = 0; !found && i < 10; i++)
+ {
+ if(i)
+ sprintf(loc, "/data/%s/com.ecere.%s-%d/lib/%s/lib", useApp ? "app" : "data", a.argv[0], i, useArch ? arch : "");
+ else
+ sprintf(loc, "/data/%s/com.ecere.%s/lib/%s/lib", useApp ? "app" : "data", a.argv[0], useArch ? arch : "");
+ sprintf(mod, "%s%s.so", loc, a.argv[0]);
+ found = FileExists(mod).isFile;
+ }
+ if(useApp)
+ useApp = false;
+ else
+ break;
+ }
+ }
+ if(useArch)
+ useArch = false;
+ else
+ break;
}
- return null;
+ return loc;
}
static bool gotInit;
0, //AKEYCODE_BUTTON_START = 108,
0, //AKEYCODE_BUTTON_SELECT = 109,
0, //AKEYCODE_BUTTON_MODE = 110,
- escape, //AKEYCODE_BUTTON_ESCAPE = 111,
- del //AKEYCODE_BUTTON_ESCAPE = 112,
+ escape, //AKEYCODE_BUTTON_ESCAPE = 111,
+ del, //AKEYCODE_BUTTON_ESCAPE = 112,
leftControl, // = 113
rightControl, // = 114
capsLock, // = 115
// Why don't we have this in the NDK :(
// default int32_t AKeyEvent_getUnichar(const AInputEvent* key_event);
+static Array<TouchPointerInfo> buildPointerInfo(AInputEvent * event)
+{
+ uint count = (uint)AMotionEvent_getPointerCount(event);
+ Array<TouchPointerInfo> infos { size = count };
+ int i;
+ for(i = 0; i < count; i++)
+ {
+ infos[i].point = { (int)AMotionEvent_getX(event, i), (int)AMotionEvent_getY(event, i) };
+ infos[i].id = (int)AMotionEvent_getPointerId(event, i);
+ infos[i].pressure = AMotionEvent_getPressure(event, i);
+ infos[i].size = AMotionEvent_getSize(event, i);
+ }
+ return infos;
+}
+
class AndroidActivity : AndroidAppGlue
{
AndroidPollSource source;
int onInputEvent(AInputEvent* event)
{
+ static Time lastTime = 0;
Window window = guiApp.desktop;
uint type = AInputEvent_getType(event);
if(type == AINPUT_EVENT_TYPE_MOTION)
{
uint actionAndIndex = AMotionEvent_getAction(event);
- uint source = AInputEvent_getSource(event);
+ //uint source = AInputEvent_getSource(event);
uint action = actionAndIndex & AMOTION_EVENT_ACTION_MASK;
- uint index = (actionAndIndex & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- uint flags = AMotionEvent_getFlags(event);
+ //uint index = (actionAndIndex & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+ //uint flags = AMotionEvent_getFlags(event);
uint meta = AMotionEvent_getMetaState(event);
- uint edge = AMotionEvent_getEdgeFlags(event);
- int64 downTime = AMotionEvent_getDownTime(event); // nanotime
- int64 eventTime = AMotionEvent_getDownTime(event);
+ //uint edge = AMotionEvent_getEdgeFlags(event);
+ //int64 downTime = AMotionEvent_getDownTime(event); // nanotime
+ //int64 eventTime = AMotionEvent_getDownTime(event);
//float axis;
Modifiers keyFlags = 0;
int x = (int)AMotionEvent_getX(event, 0);
int y = (int)AMotionEvent_getY(event, 0);
bool shift = (meta & AMETA_SHIFT_ON) ? true : false;
bool alt = (meta & AMETA_ALT_ON) ? true : false;
- bool sym = (meta & AMETA_SYM_ON) ? true : false;
+ //bool sym = (meta & AMETA_SYM_ON) ? true : false;
keyFlags.shift = shift;
keyFlags.alt = alt;
break;
*/
case AMOTION_EVENT_ACTION_DOWN:
+ {
+ Time time = GetTime();
+ bool result = true;
+ if(Abs(x - mouseX) < 40 && Abs(y - mouseY) < 40 && time - lastTime < 0.3)
+ if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick, x, y, &keyFlags, false, true))
+ result = false;
+ lastTime = time;
mouseX = x, mouseY = y;
- window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown, x, y, &keyFlags, false, true);
+ if(result)
+ // TOCHECK: Should we do result = here?
+ window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown, x, y, &keyFlags, false, true);
+ if(result)
+ {
+ Array<TouchPointerInfo> infos = buildPointerInfo(event);
+ window.MultiTouchMessage(down, infos, &keyFlags, false, true);
+ delete infos;
+ }
break;
+ }
case AMOTION_EVENT_ACTION_UP:
mouseX = x, mouseY = y;
- window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x, y, &keyFlags, false, true);
+ if(window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x, y, &keyFlags, false, true))
+ {
+ Array<TouchPointerInfo> infos = buildPointerInfo(event);
+ window.MultiTouchMessage(up, infos, &keyFlags, false, true);
+ delete infos;
+ }
break;
case AMOTION_EVENT_ACTION_MOVE:
mouseX = x, mouseY = y;
- window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &keyFlags, false, true);
+ if(window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &keyFlags, false, true))
+ {
+ Array<TouchPointerInfo> infos = buildPointerInfo(event);
+ window.MultiTouchMessage(move, infos, &keyFlags, false, true);
+ delete infos;
+ }
break;
case AMOTION_EVENT_ACTION_CANCEL: break;
case AMOTION_EVENT_ACTION_OUTSIDE: break;
- case AMOTION_EVENT_ACTION_POINTER_DOWN: break;
- case AMOTION_EVENT_ACTION_POINTER_UP: break;
+ case AMOTION_EVENT_ACTION_POINTER_DOWN:
+ {
+ Array<TouchPointerInfo> infos = buildPointerInfo(event);
+ window.MultiTouchMessage(pointerDown, infos, &keyFlags, false, true);
+ delete infos;
+ break;
+ }
+ case AMOTION_EVENT_ACTION_POINTER_UP:
+ {
+ Array<TouchPointerInfo> infos = buildPointerInfo(event);
+ window.MultiTouchMessage(pointerUp, infos, &keyFlags, false, true);
+ delete infos;
+ break;
+ }
}
return 1;
}
else if(type == AINPUT_EVENT_TYPE_KEY)
{
uint action = AKeyEvent_getAction(event);
- uint flags = AKeyEvent_getFlags(event);
+ //uint flags = AKeyEvent_getFlags(event);
uint keyCode = AKeyEvent_getKeyCode(event);
uint meta = AKeyEvent_getMetaState(event);
Key key = keyCodeTable[keyCode];
bool shift = (meta & AMETA_SHIFT_ON) ? true : false;
bool alt = (meta & AMETA_ALT_ON || meta & AMETA_ALT_LEFT_ON || meta & AMETA_ALT_RIGHT_ON) ? true : false;
- bool metaMeta = (meta & AMETA_META_ON || meta & AMETA_META_LEFT_ON || meta & AMETA_META_RIGHT_ON) ? true : false;
- bool sym = (meta & AMETA_SYM_ON) ? true : false;
+ //bool metaMeta = (meta & AMETA_META_ON || meta & AMETA_META_LEFT_ON || meta & AMETA_META_RIGHT_ON) ? true : false;
+ //bool sym = (meta & AMETA_SYM_ON) ? true : false;
//unichar ch = AKeyEvent_getUnichar(event);
unichar ch = 0;
for(c = app.classes.first; c && !eClass_IsDerived(c, class(GuiApplication)); c = c.next);
if(!c) c = class(GuiApplication);
+ guiApp.lockMutex.Release(); // TOCHECK: Seems the evolve is losing our mutex lock here ?
+
// Evolve the Application into it
eInstance_Evolve((Instance *)&__androidCurrentModule, c);
guiApp = (GuiApplication)__androidCurrentModule;
{
- String skin = guiApp.skin;
+ const String skin = guiApp.skin;
*&guiApp.currentSkin = null;
guiApp.SelectSkin(skin);
}
+ guiApp.lockMutex.Wait();
+
// Call Main()
((void (*)(void *))(void *)__androidCurrentModule._vTbl[12])(__androidCurrentModule);
}