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

View File

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

View File

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

View File

@ -40,9 +40,9 @@ namespace priv
ResourceStream::ResourceStream(const std::string& filename) :
m_file (NULL)
{
ActivityStates* states = getActivity(NULL);
Lock lock(states->mutex);
m_file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
ActivityStates& states = getActivity();
Lock lock(states.mutex);
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
ActivityStates* states = getActivity(NULL);
Lock lock(states->mutex);
ActivityStates& states = getActivity();
Lock lock(states.mutex);
// Initializes JNI
jint lResult;
jint lFlags = 0;
JavaVM* lJavaVM = states->activity->vm;
JNIEnv* lJNIEnv = states->activity->env;
JavaVM* lJavaVM = states.activity->vm;
JNIEnv* lJNIEnv = states.activity->env;
JavaVMAttachArgs lJavaVMAttachArgs;
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;
// Retrieves NativeActivity
jobject lNativeActivity = states->activity->clazz;
jobject lNativeActivity = states.activity->clazz;
jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);
// Retrieves Context.INPUT_METHOD_SERVICE
@ -138,10 +138,10 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
{
ALooper_pollAll(0, NULL, NULL, NULL);
priv::ActivityStates* states = priv::getActivity(NULL);
Lock lock(states->mutex);
priv::ActivityStates& states = priv::getActivity();
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);
priv::ActivityStates* states = priv::getActivity(NULL);
Lock lock(states->mutex);
priv::ActivityStates& states = priv::getActivity();
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);
priv::ActivityStates* states = priv::getActivity(NULL);
Lock lock(states->mutex);
priv::ActivityStates& states = priv::getActivity();
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);
priv::ActivityStates* states = priv::getActivity(NULL);
Lock lock(states->mutex);
priv::ActivityStates& states = priv::getActivity();
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()
{
// Get the activity states
priv::ActivityStates* states = priv::getActivity(NULL);
Lock lock(states->mutex);
priv::ActivityStates& states = priv::getActivity();
Lock lock(states.mutex);
return VideoMode(states->screenSize.x, states->screenSize.y);
return VideoMode(states.screenSize.x, states.screenSize.y);
}
} // namespace priv

View File

@ -65,19 +65,19 @@ WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsign
, m_windowBeingDestroyed(false)
, m_hasFocus(false)
{
ActivityStates* states = getActivity(NULL);
Lock lock(states->mutex);
priv::ActivityStates& states = priv::getActivity();
Lock lock(states.mutex);
if (style& Style::Fullscreen)
states->fullscreen = true;
states.fullscreen = true;
WindowImplAndroid::singleInstance = this;
states->forwardEvent = forwardEvent;
states.forwardEvent = forwardEvent;
// 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
{
ActivityStates* states = getActivity(NULL);
Lock lock(states->mutex);
ActivityStates& states = getActivity();
Lock lock(states.mutex);
return states->window;
return states.window;
}
@ -104,22 +104,22 @@ void WindowImplAndroid::processEvents()
// Process incoming OS events
ALooper_pollAll(0, NULL, NULL, NULL);
ActivityStates* states = getActivity(NULL);
sf::Lock lock(states->mutex);
ActivityStates& states = getActivity();
Lock lock(states.mutex);
if (m_windowBeingCreated)
{
states->context->createSurface(states->window);
states.context->createSurface(states.window);
m_windowBeingCreated = false;
}
if (m_windowBeingDestroyed)
{
states->context->destroySurface();
states.context->destroySurface();
m_windowBeingDestroyed = false;
}
states->updated = true;
states.updated = true;
}
@ -219,12 +219,12 @@ void WindowImplAndroid::forwardEvent(const Event& event)
{
if (WindowImplAndroid::singleInstance != NULL)
{
ActivityStates* states = getActivity(NULL);
ActivityStates& states = getActivity();
if (event.type == Event::GainedFocus)
{
WindowImplAndroid::singleInstance->m_size.x = ANativeWindow_getWidth(states->window);
WindowImplAndroid::singleInstance->m_size.y = ANativeWindow_getHeight(states->window);
WindowImplAndroid::singleInstance->m_size.x = ANativeWindow_getWidth(states.window);
WindowImplAndroid::singleInstance->m_size.y = ANativeWindow_getHeight(states.window);
WindowImplAndroid::singleInstance->m_windowBeingCreated = 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)
{
ActivityStates* states = getActivity(NULL);
Lock lock(states->mutex);
ActivityStates& states = getActivity();
Lock lock(states.mutex);
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;
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;
@ -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
jint lResult;
jint lFlags = 0;
JavaVM* lJavaVM = states->activity->vm;
JNIEnv* lJNIEnv = states->activity->env;
JavaVM* lJavaVM = states.activity->vm;
JNIEnv* lJNIEnv = states.activity->env;
JavaVMAttachArgs lJavaVMAttachArgs;
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 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 action = AMotionEvent_getAction(_event);
@ -468,18 +468,18 @@ int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* s
event.mouseMove.x = x;
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)
{
if (states->touchEvents[id].x == x && states->touchEvents[id].y == y)
if (states.touchEvents[id].x == x && states.touchEvents[id].y == y)
continue;
event.touch.finger = id;
event.touch.x = x;
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);
@ -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 action = AMotionEvent_getAction(_event);
@ -512,7 +512,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Act
event.mouseButton.y = y;
if (id >= 0 && id < Mouse::ButtonCount)
states->isButtonPressed[id] = true;
states.isButtonPressed[id] = true;
}
else if (device & AINPUT_SOURCE_TOUCHSCREEN)
{
@ -521,7 +521,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Act
event.touch.x = x;
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
@ -534,7 +534,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Act
event.mouseButton.y = y;
if (id >= 0 && id < Mouse::ButtonCount)
states->isButtonPressed[id] = false;
states.isButtonPressed[id] = false;
}
else if (device & AINPUT_SOURCE_TOUCHSCREEN)
{
@ -543,7 +543,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Act
event.touch.x = x;
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)
{
// Retrieve activity states
ActivityStates* states = getActivity(NULL);
Lock lock(states->mutex);
ActivityStates& states = getActivity();
Lock lock(states.mutex);
// Initializes JNI
jint lResult;
jint lFlags = 0;
JavaVM* lJavaVM = states->activity->vm;
JNIEnv* lJNIEnv = states->activity->env;
JavaVM* lJavaVM = states.activity->vm;
JNIEnv* lJNIEnv = states.activity->env;
JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6;

View File

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

View File

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