Make android callback thread safe
This commit is contained in:
parent
febad27342
commit
a96071f9d3
@ -9,6 +9,7 @@
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include <assert.h>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include "os.h"
|
||||
#include "CContextEGL.h"
|
||||
@ -43,7 +44,7 @@ ANDROID_SAVE_CHARS_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
|
||||
|
||||
// Call when android keyboard is opened or close, and save its height for
|
||||
// moving screen
|
||||
int g_keyboard_height = 0;
|
||||
std::atomic<int> g_keyboard_height(0);
|
||||
|
||||
#define MAKE_ANDROID_SAVE_KBD_HEIGHT_CALLBACK(x) JNIEXPORT void JNICALL Java_ ## x##_SuperTuxKartActivity_saveKeyboardHeight(JNIEnv* env, jobject this_obj, jint height)
|
||||
#define ANDROID_SAVE_KBD_HEIGHT_CALLBACK(PKG_NAME) MAKE_ANDROID_SAVE_KBD_HEIGHT_CALLBACK(PKG_NAME)
|
||||
@ -51,7 +52,7 @@ int g_keyboard_height = 0;
|
||||
extern "C"
|
||||
ANDROID_SAVE_KBD_HEIGHT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
|
||||
{
|
||||
g_keyboard_height = (int)height;
|
||||
g_keyboard_height.store((int)height);
|
||||
}
|
||||
|
||||
namespace irr
|
||||
@ -227,8 +228,9 @@ void CIrrDeviceAndroid::printConfig()
|
||||
|
||||
u32 CIrrDeviceAndroid::getOnScreenKeyboardHeight() const
|
||||
{
|
||||
if (g_keyboard_height > 0)
|
||||
return g_keyboard_height;
|
||||
int height = g_keyboard_height.load();
|
||||
if (height > 0)
|
||||
return height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -685,9 +685,11 @@ namespace GUIEngine
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "utils/debug.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include <irrlicht.h>
|
||||
#include <mutex>
|
||||
|
||||
using namespace irr::gui;
|
||||
using namespace irr::video;
|
||||
@ -716,6 +718,10 @@ namespace GUIEngine
|
||||
int large_font_height;
|
||||
int small_font_height;
|
||||
int title_font_height;
|
||||
#ifdef ANDROID
|
||||
std::mutex m_gui_functions_mutex;
|
||||
std::vector<std::function<void()> > m_gui_functions;
|
||||
#endif
|
||||
}
|
||||
using namespace Private;
|
||||
|
||||
@ -1144,6 +1150,15 @@ namespace GUIEngine
|
||||
assert(g_skin->getReferenceCount() == 1);
|
||||
} // reloadSkin
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
void addGUIFunctionBeforeRendering(std::function<void()> func)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
std::lock_guard<std::mutex> lock(m_gui_functions_mutex);
|
||||
m_gui_functions.push_back(func);
|
||||
#endif
|
||||
} // addGUIFunctionBeforeRendering
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/** \brief called on every frame to trigger the rendering of the GUI.
|
||||
* \param elapsed_time Time since last rendering calls (in seconds).
|
||||
@ -1158,6 +1173,21 @@ namespace GUIEngine
|
||||
// Not yet initialized, or already cleaned up
|
||||
if (g_skin == NULL) return;
|
||||
|
||||
#ifdef ANDROID
|
||||
// Run all GUI functions first (if any)
|
||||
std::unique_lock<std::mutex> ul(m_gui_functions_mutex);
|
||||
if (!m_gui_functions.empty())
|
||||
{
|
||||
std::vector<std::function<void()> > functions;
|
||||
std::swap(functions, m_gui_functions);
|
||||
ul.unlock();
|
||||
for (auto& f : functions)
|
||||
f();
|
||||
}
|
||||
else
|
||||
ul.unlock();
|
||||
#endif
|
||||
|
||||
// ---- menu drawing
|
||||
|
||||
// draw background image and sections
|
||||
|
@ -34,6 +34,7 @@ namespace irr
|
||||
namespace video { class IVideoDriver; class ITexture; }
|
||||
}
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "utils/constants.hpp"
|
||||
@ -248,6 +249,10 @@ namespace GUIEngine
|
||||
*/
|
||||
void reloadSkin();
|
||||
|
||||
/**
|
||||
* \brief Add gui-related function before rendering GUI (from other thread)
|
||||
*/
|
||||
void addGUIFunctionBeforeRendering(std::function<void()> func);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -246,8 +246,7 @@ EventPropagation TextBoxWidget::leftPressed (const int playerID)
|
||||
extern "C"
|
||||
ANDROID_EDITTEXT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
|
||||
{
|
||||
TextBoxWidget* tb = dynamic_cast<TextBoxWidget*>(getFocusForPlayer(0));
|
||||
if (!tb || (int)widget_id != tb->getID() || text == NULL)
|
||||
if (text == NULL)
|
||||
return;
|
||||
|
||||
const char* utf8_text = env->GetStringUTFChars(text, NULL);
|
||||
@ -262,8 +261,17 @@ ANDROID_EDITTEXT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
|
||||
utf32line.push_back(0);
|
||||
|
||||
core::stringw to_editbox(&utf32line[0]);
|
||||
tb->getIrrlichtElement<MyCGUIEditBox>()->fromAndroidEditText(
|
||||
to_editbox, start, end, composing_start, composing_end);
|
||||
env->ReleaseStringUTFChars(text, utf8_text);
|
||||
|
||||
GUIEngine::addGUIFunctionBeforeRendering([widget_id, to_editbox, start,
|
||||
end, composing_start, composing_end]()
|
||||
{
|
||||
TextBoxWidget* tb =
|
||||
dynamic_cast<TextBoxWidget*>(getFocusForPlayer(0));
|
||||
if (!tb || (int)widget_id != tb->getID())
|
||||
return;
|
||||
tb->getIrrlichtElement<MyCGUIEditBox>()->fromAndroidEditText(
|
||||
to_editbox, start, end, composing_start, composing_end);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user