Simplify management of ActivityStates

This commit is contained in:
Vittorio Romeo 2021-11-19 00:21:04 +00:00 committed by Lukas Dürrenberger
parent dc88cbd81e
commit ef8fee5356
10 changed files with 102 additions and 86 deletions

View File

@ -46,6 +46,7 @@
#include <android/window.h> #include <android/window.h>
#include <android/native_activity.h> #include <android/native_activity.h>
#include <cstring> #include <cstring>
#include <cassert>
#define SF_GLAD_EGL_IMPLEMENTATION #define SF_GLAD_EGL_IMPLEMENTATION
#include <glad/egl.h> #include <glad/egl.h>
@ -70,10 +71,10 @@ int getAndroidApiLevel(ANativeActivity* activity)
jfieldID sdkIntFieldID = lJNIEnv->GetStaticFieldID(versionClass, "SDK_INT", "I"); jfieldID sdkIntFieldID = lJNIEnv->GetStaticFieldID(versionClass, "SDK_INT", "I");
if (sdkIntFieldID == NULL) if (sdkIntFieldID == NULL)
return 0; return 0;
jint sdkInt = 0; jint sdkInt = 0;
sdkInt = lJNIEnv->GetStaticIntField(versionClass, sdkIntFieldID); sdkInt = lJNIEnv->GetStaticIntField(versionClass, sdkIntFieldID);
return sdkInt; return sdkInt;
} }
@ -81,6 +82,8 @@ int getAndroidApiLevel(ANativeActivity* activity)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
ActivityStates* retrieveStates(ANativeActivity* activity) ActivityStates* retrieveStates(ANativeActivity* activity)
{ {
assert(activity != NULL);
// Hide the ugly cast we find in each callback function // Hide the ugly cast we find in each callback function
return (ActivityStates*)activity->instance; return (ActivityStates*)activity->instance;
} }
@ -97,8 +100,8 @@ static void initializeMain(ActivityStates* states)
states->looper = looper; states->looper = looper;
/** /**
* Acquire increments a reference counter on the looper. This keeps android * Acquire increments a reference counter on the looper. This keeps android
* from collecting it before the activity thread has a chance to detach its * from collecting it before the activity thread has a chance to detach its
* input queue. * input queue.
*/ */
ALooper_acquire(states->looper); ALooper_acquire(states->looper);
@ -175,7 +178,7 @@ void goToFullscreenMode(ANativeActivity* activity)
// Default flags // Default flags
jint flags = 0; jint flags = 0;
// API Level 14 // API Level 14
if (apiLevel >= 14) if (apiLevel >= 14)
{ {
@ -327,7 +330,7 @@ static void onDestroy(ANativeActivity* activity)
delete states; delete states;
// Reset the activity pointer for all modules // Reset the activity pointer for all modules
sf::priv::getActivity(NULL, true); sf::priv::resetActivity(NULL);
// The application should now terminate // The application should now terminate
} }
@ -509,7 +512,7 @@ JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedSt
states->terminated = false; states->terminated = false;
// Share it across the SFML modules // Share it across the SFML modules
sf::priv::getActivity(states, true); sf::priv::resetActivity(states);
// These functions will update the activity states and therefore, will allow // These functions will update the activity states and therefore, will allow
// SFML to be kept in the know // SFML to be kept in the know

View File

@ -29,6 +29,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/Android/Activity.hpp> #include <SFML/System/Android/Activity.hpp>
#include <android/log.h> #include <android/log.h>
#include <cassert>
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "sfml-error", __VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "sfml-error", __VA_ARGS__))
@ -56,14 +57,24 @@ namespace sf
{ {
namespace priv namespace priv
{ {
ActivityStates* getActivity(ActivityStates* initializedStates, bool reset)
ActivityStates*& getActivityStatesPtr()
{ {
static ActivityStates* states = NULL; static ActivityStates* states = NULL;
if (!states || reset)
states = initializedStates;
return states; return states;
} }
void resetActivity(ActivityStates* initializedStates)
{
getActivityStatesPtr() = initializedStates;
}
ActivityStates& getActivity()
{
ActivityStates* const states = getActivityStatesPtr();
assert(states != NULL);
return *states;
}
} }
} }

View File

@ -91,7 +91,9 @@ struct ActivityStates
LogcatStream logcat; LogcatStream logcat;
}; };
SFML_SYSTEM_API ActivityStates* getActivity(ActivityStates* initializedStates=NULL, bool reset=false); SFML_SYSTEM_API ActivityStates*& getActivityStatesPtr();
SFML_SYSTEM_API void resetActivity(ActivityStates* initializedStates);
SFML_SYSTEM_API ActivityStates& getActivity();
} // namespace priv } // namespace priv
} // namespace sf } // namespace sf

View File

@ -33,7 +33,7 @@ namespace sf
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
ANativeActivity* getNativeActivity() ANativeActivity* getNativeActivity()
{ {
return priv::getActivity()->activity; return priv::getActivity().activity;
} }
} // namespace sf } // namespace sf

View File

@ -40,9 +40,9 @@ namespace priv
ResourceStream::ResourceStream(const std::string& filename) : ResourceStream::ResourceStream(const std::string& filename) :
m_file (NULL) m_file (NULL)
{ {
ActivityStates* states = getActivity(NULL); ActivityStates& states = getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
m_file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN); m_file = AAssetManager_open(states.activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
} }

View File

@ -48,15 +48,15 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
{ {
// todo: Check if the window is active // todo: Check if the window is active
ActivityStates* states = getActivity(NULL); ActivityStates& states = getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
// Initializes JNI // Initializes JNI
jint lResult; jint lResult;
jint lFlags = 0; jint lFlags = 0;
JavaVM* lJavaVM = states->activity->vm; JavaVM* lJavaVM = states.activity->vm;
JNIEnv* lJNIEnv = states->activity->env; JNIEnv* lJNIEnv = states.activity->env;
JavaVMAttachArgs lJavaVMAttachArgs; JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6; lJavaVMAttachArgs.version = JNI_VERSION_1_6;
@ -69,7 +69,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
err() << "Failed to initialize JNI, couldn't switch the keyboard visibility" << std::endl; err() << "Failed to initialize JNI, couldn't switch the keyboard visibility" << std::endl;
// Retrieves NativeActivity // Retrieves NativeActivity
jobject lNativeActivity = states->activity->clazz; jobject lNativeActivity = states.activity->clazz;
jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity); jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);
// Retrieves Context.INPUT_METHOD_SERVICE // Retrieves Context.INPUT_METHOD_SERVICE
@ -138,10 +138,10 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
{ {
ALooper_pollAll(0, NULL, NULL, NULL); ALooper_pollAll(0, NULL, NULL, NULL);
priv::ActivityStates* states = priv::getActivity(NULL); priv::ActivityStates& states = priv::getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
return states->isButtonPressed[button]; return states.isButtonPressed[button];
} }
@ -150,10 +150,10 @@ Vector2i InputImpl::getMousePosition()
{ {
ALooper_pollAll(0, NULL, NULL, NULL); ALooper_pollAll(0, NULL, NULL, NULL);
priv::ActivityStates* states = priv::getActivity(NULL); priv::ActivityStates& states = priv::getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
return states->mousePosition; return states.mousePosition;
} }
@ -183,10 +183,10 @@ bool InputImpl::isTouchDown(unsigned int finger)
{ {
ALooper_pollAll(0, NULL, NULL, NULL); ALooper_pollAll(0, NULL, NULL, NULL);
priv::ActivityStates* states = priv::getActivity(NULL); priv::ActivityStates& states = priv::getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
return states->touchEvents.find(finger) != states->touchEvents.end(); return states.touchEvents.find(finger) != states.touchEvents.end();
} }
@ -195,10 +195,10 @@ Vector2i InputImpl::getTouchPosition(unsigned int finger)
{ {
ALooper_pollAll(0, NULL, NULL, NULL); ALooper_pollAll(0, NULL, NULL, NULL);
priv::ActivityStates* states = priv::getActivity(NULL); priv::ActivityStates& states = priv::getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
return states->touchEvents.find(finger)->second; return states.touchEvents.find(finger)->second;
} }

View File

@ -52,10 +52,10 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
VideoMode VideoModeImpl::getDesktopMode() VideoMode VideoModeImpl::getDesktopMode()
{ {
// Get the activity states // Get the activity states
priv::ActivityStates* states = priv::getActivity(NULL); priv::ActivityStates& states = priv::getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
return VideoMode(states->screenSize.x, states->screenSize.y); return VideoMode(states.screenSize.x, states.screenSize.y);
} }
} // namespace priv } // namespace priv

View File

@ -65,19 +65,19 @@ WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsign
, m_windowBeingDestroyed(false) , m_windowBeingDestroyed(false)
, m_hasFocus(false) , m_hasFocus(false)
{ {
ActivityStates* states = getActivity(NULL); priv::ActivityStates& states = priv::getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
if (style& Style::Fullscreen) if (style& Style::Fullscreen)
states->fullscreen = true; states.fullscreen = true;
WindowImplAndroid::singleInstance = this; WindowImplAndroid::singleInstance = this;
states->forwardEvent = forwardEvent; states.forwardEvent = forwardEvent;
// Register process event callback // Register process event callback
states->processEvent = processEvent; states.processEvent = processEvent;
states->initialized = true; states.initialized = true;
} }
@ -91,10 +91,10 @@ WindowImplAndroid::~WindowImplAndroid()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowHandle WindowImplAndroid::getSystemHandle() const WindowHandle WindowImplAndroid::getSystemHandle() const
{ {
ActivityStates* states = getActivity(NULL); ActivityStates& states = getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
return states->window; return states.window;
} }
@ -104,22 +104,22 @@ void WindowImplAndroid::processEvents()
// Process incoming OS events // Process incoming OS events
ALooper_pollAll(0, NULL, NULL, NULL); ALooper_pollAll(0, NULL, NULL, NULL);
ActivityStates* states = getActivity(NULL); ActivityStates& states = getActivity();
sf::Lock lock(states->mutex); Lock lock(states.mutex);
if (m_windowBeingCreated) if (m_windowBeingCreated)
{ {
states->context->createSurface(states->window); states.context->createSurface(states.window);
m_windowBeingCreated = false; m_windowBeingCreated = false;
} }
if (m_windowBeingDestroyed) if (m_windowBeingDestroyed)
{ {
states->context->destroySurface(); states.context->destroySurface();
m_windowBeingDestroyed = false; m_windowBeingDestroyed = false;
} }
states->updated = true; states.updated = true;
} }
@ -219,12 +219,12 @@ void WindowImplAndroid::forwardEvent(const Event& event)
{ {
if (WindowImplAndroid::singleInstance != NULL) if (WindowImplAndroid::singleInstance != NULL)
{ {
ActivityStates* states = getActivity(NULL); ActivityStates& states = getActivity();
if (event.type == Event::GainedFocus) if (event.type == Event::GainedFocus)
{ {
WindowImplAndroid::singleInstance->m_size.x = ANativeWindow_getWidth(states->window); WindowImplAndroid::singleInstance->m_size.x = ANativeWindow_getWidth(states.window);
WindowImplAndroid::singleInstance->m_size.y = ANativeWindow_getHeight(states->window); WindowImplAndroid::singleInstance->m_size.y = ANativeWindow_getHeight(states.window);
WindowImplAndroid::singleInstance->m_windowBeingCreated = true; WindowImplAndroid::singleInstance->m_windowBeingCreated = true;
WindowImplAndroid::singleInstance->m_hasFocus = true; WindowImplAndroid::singleInstance->m_hasFocus = true;
} }
@ -242,14 +242,14 @@ void WindowImplAndroid::forwardEvent(const Event& event)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
int WindowImplAndroid::processEvent(int fd, int events, void* data) int WindowImplAndroid::processEvent(int fd, int events, void* data)
{ {
ActivityStates* states = getActivity(NULL); ActivityStates& states = getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
AInputEvent* _event = NULL; AInputEvent* _event = NULL;
if (AInputQueue_getEvent(states->inputQueue, &_event) >= 0) if (AInputQueue_getEvent(states.inputQueue, &_event) >= 0)
{ {
if (AInputQueue_preDispatchEvent(states->inputQueue, _event)) if (AInputQueue_preDispatchEvent(states.inputQueue, _event))
return 1; return 1;
int handled = 0; int handled = 0;
@ -306,7 +306,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
} }
AInputQueue_finishEvent(states->inputQueue, _event, handled); AInputQueue_finishEvent(states.inputQueue, _event, handled);
} }
return 1; return 1;
@ -314,14 +314,14 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
int WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* states) int WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates& states)
{ {
// Prepare the Java virtual machine // Prepare the Java virtual machine
jint lResult; jint lResult;
jint lFlags = 0; jint lFlags = 0;
JavaVM* lJavaVM = states->activity->vm; JavaVM* lJavaVM = states.activity->vm;
JNIEnv* lJNIEnv = states->activity->env; JNIEnv* lJNIEnv = states.activity->env;
JavaVMAttachArgs lJavaVMAttachArgs; JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6; lJavaVMAttachArgs.version = JNI_VERSION_1_6;
@ -378,7 +378,7 @@ int WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* s
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states) int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates& states)
{ {
int32_t device = AInputEvent_getSource(_event); int32_t device = AInputEvent_getSource(_event);
int32_t action = AKeyEvent_getAction(_event); int32_t action = AKeyEvent_getAction(_event);
@ -442,7 +442,7 @@ int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* stat
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states) int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates& states)
{ {
int32_t device = AInputEvent_getSource(_event); int32_t device = AInputEvent_getSource(_event);
int32_t action = AMotionEvent_getAction(_event); int32_t action = AMotionEvent_getAction(_event);
@ -468,18 +468,18 @@ int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* s
event.mouseMove.x = x; event.mouseMove.x = x;
event.mouseMove.y = y; event.mouseMove.y = y;
states->mousePosition = Vector2i(event.mouseMove.x, event.mouseMove.y); states.mousePosition = Vector2i(event.mouseMove.x, event.mouseMove.y);
} }
else if (device & AINPUT_SOURCE_TOUCHSCREEN) else if (device & AINPUT_SOURCE_TOUCHSCREEN)
{ {
if (states->touchEvents[id].x == x && states->touchEvents[id].y == y) if (states.touchEvents[id].x == x && states.touchEvents[id].y == y)
continue; continue;
event.touch.finger = id; event.touch.finger = id;
event.touch.x = x; event.touch.x = x;
event.touch.y = y; event.touch.y = y;
states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); states.touchEvents[id] = Vector2i(event.touch.x, event.touch.y);
} }
forwardEvent(event); forwardEvent(event);
@ -489,7 +489,7 @@ int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* s
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states) int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates& states)
{ {
int32_t device = AInputEvent_getSource(_event); int32_t device = AInputEvent_getSource(_event);
int32_t action = AMotionEvent_getAction(_event); int32_t action = AMotionEvent_getAction(_event);
@ -512,7 +512,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Act
event.mouseButton.y = y; event.mouseButton.y = y;
if (id >= 0 && id < Mouse::ButtonCount) if (id >= 0 && id < Mouse::ButtonCount)
states->isButtonPressed[id] = true; states.isButtonPressed[id] = true;
} }
else if (device & AINPUT_SOURCE_TOUCHSCREEN) else if (device & AINPUT_SOURCE_TOUCHSCREEN)
{ {
@ -521,7 +521,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Act
event.touch.x = x; event.touch.x = x;
event.touch.y = y; event.touch.y = y;
states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); states.touchEvents[id] = Vector2i(event.touch.x, event.touch.y);
} }
} }
else else
@ -534,7 +534,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Act
event.mouseButton.y = y; event.mouseButton.y = y;
if (id >= 0 && id < Mouse::ButtonCount) if (id >= 0 && id < Mouse::ButtonCount)
states->isButtonPressed[id] = false; states.isButtonPressed[id] = false;
} }
else if (device & AINPUT_SOURCE_TOUCHSCREEN) else if (device & AINPUT_SOURCE_TOUCHSCREEN)
{ {
@ -543,7 +543,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Act
event.touch.x = x; event.touch.x = x;
event.touch.y = y; event.touch.y = y;
states->touchEvents.erase(id); states.touchEvents.erase(id);
} }
} }
@ -678,15 +678,15 @@ Keyboard::Key WindowImplAndroid::androidKeyToSF(int32_t key)
int WindowImplAndroid::getUnicode(AInputEvent* event) int WindowImplAndroid::getUnicode(AInputEvent* event)
{ {
// Retrieve activity states // Retrieve activity states
ActivityStates* states = getActivity(NULL); ActivityStates& states = getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
// Initializes JNI // Initializes JNI
jint lResult; jint lResult;
jint lFlags = 0; jint lFlags = 0;
JavaVM* lJavaVM = states->activity->vm; JavaVM* lJavaVM = states.activity->vm;
JNIEnv* lJNIEnv = states->activity->env; JNIEnv* lJNIEnv = states.activity->env;
JavaVMAttachArgs lJavaVMAttachArgs; JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6; lJavaVMAttachArgs.version = JNI_VERSION_1_6;

View File

@ -210,10 +210,10 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static int processEvent(int fd, int events, void* data); static int processEvent(int fd, int events, void* data);
static int processScrollEvent(AInputEvent* _event, ActivityStates* states); static int processScrollEvent(AInputEvent* _event, ActivityStates& states);
static int processKeyEvent(AInputEvent* _event, ActivityStates* states); static int processKeyEvent(AInputEvent* _event, ActivityStates& states);
static int processMotionEvent(AInputEvent* _event, ActivityStates* states); static int processMotionEvent(AInputEvent* _event, ActivityStates& states);
static int processPointerEvent(bool isDown, AInputEvent* event, ActivityStates* states); static int processPointerEvent(bool isDown, AInputEvent* event, ActivityStates& states);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Convert a Android key to SFML key code /// \brief Convert a Android key to SFML key code

View File

@ -57,10 +57,10 @@ namespace
#if defined(SFML_SYSTEM_ANDROID) #if defined(SFML_SYSTEM_ANDROID)
// On Android, its native activity handles this for us // On Android, its native activity handles this for us
sf::priv::ActivityStates* states = sf::priv::getActivity(NULL); sf::priv::ActivityStates& states = sf::priv::getActivity();
sf::Lock lock(states->mutex); sf::Lock lock(states.mutex);
return states->display; return states.display;
#endif #endif
@ -143,10 +143,10 @@ m_config (NULL)
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
// On Android, we must save the created context // On Android, we must save the created context
ActivityStates* states = getActivity(NULL); ActivityStates& states = getActivity();
Lock lock(states->mutex); Lock lock(states.mutex);
states->context = this; states.context = this;
#endif #endif