Merge branch 'android_improvements'
This commit is contained in:
commit
3f69629d0c
|
@ -42,6 +42,7 @@
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
#include <SFML/System/Thread.hpp>
|
#include <SFML/System/Thread.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
#include <SFML/System/Lock.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
#include <android/window.h>
|
#include <android/window.h>
|
||||||
#include <android/native_activity.h>
|
#include <android/native_activity.h>
|
||||||
|
|
||||||
|
@ -94,12 +95,6 @@ void* main(ActivityStates* states)
|
||||||
// Initialize the thread before giving the hand
|
// Initialize the thread before giving the hand
|
||||||
initializeMain(states);
|
initializeMain(states);
|
||||||
|
|
||||||
{
|
|
||||||
Lock lock(states->mutex);
|
|
||||||
|
|
||||||
states->initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(seconds(0.5));
|
sleep(seconds(0.5));
|
||||||
::main(0, NULL);
|
::main(0, NULL);
|
||||||
|
|
||||||
|
@ -119,6 +114,80 @@ void* main(ActivityStates* states)
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void goToFullscreenMode(ANativeActivity* activity)
|
||||||
|
{
|
||||||
|
// Hide the status bar
|
||||||
|
ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN,
|
||||||
|
AWINDOW_FLAG_FULLSCREEN);
|
||||||
|
|
||||||
|
// Hide the navigation bar
|
||||||
|
JavaVM* lJavaVM = activity->vm;
|
||||||
|
JNIEnv* lJNIEnv = activity->env;
|
||||||
|
|
||||||
|
jobject objectActivity = activity->clazz;
|
||||||
|
jclass classActivity = lJNIEnv->GetObjectClass(objectActivity);
|
||||||
|
|
||||||
|
jmethodID methodGetWindow = lJNIEnv->GetMethodID(classActivity, "getWindow", "()Landroid/view/Window;");
|
||||||
|
jobject objectWindow = lJNIEnv->CallObjectMethod(objectActivity, methodGetWindow);
|
||||||
|
|
||||||
|
jclass classWindow = lJNIEnv->FindClass("android/view/Window");
|
||||||
|
jmethodID methodGetDecorView = lJNIEnv->GetMethodID(classWindow, "getDecorView", "()Landroid/view/View;");
|
||||||
|
jobject objectDecorView = lJNIEnv->CallObjectMethod(objectWindow, methodGetDecorView);
|
||||||
|
|
||||||
|
jclass classView = lJNIEnv->FindClass("android/view/View");
|
||||||
|
|
||||||
|
jfieldID FieldSYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_LOW_PROFILE", "I");
|
||||||
|
jint SYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_LOW_PROFILE);
|
||||||
|
|
||||||
|
jfieldID FieldSYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_FULLSCREEN", "I");
|
||||||
|
jint SYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_FULLSCREEN);
|
||||||
|
|
||||||
|
//jfieldID FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I");
|
||||||
|
//jint SYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
||||||
|
|
||||||
|
jmethodID methodsetSystemUiVisibility = lJNIEnv->GetMethodID(classView, "setSystemUiVisibility", "(I)V");
|
||||||
|
lJNIEnv->CallVoidMethod(objectDecorView, methodsetSystemUiVisibility, SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN | 0x00001000);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void getScreenSizeInPixels(ANativeActivity* activity, int* width, int* height)
|
||||||
|
{
|
||||||
|
// Perform the following java code:
|
||||||
|
//
|
||||||
|
// DisplayMetrics dm = new DisplayMetrics();
|
||||||
|
// getWindowManager().getDefaultDisplay().getMetrics(dm);
|
||||||
|
|
||||||
|
JavaVM* lJavaVM = activity->vm;
|
||||||
|
JNIEnv* lJNIEnv = activity->env;
|
||||||
|
|
||||||
|
jobject objectActivity = activity->clazz;
|
||||||
|
jclass classActivity = lJNIEnv->GetObjectClass(objectActivity);
|
||||||
|
|
||||||
|
jclass classDisplayMetrics = lJNIEnv->FindClass("android/util/DisplayMetrics");
|
||||||
|
jmethodID initDisplayMetrics = lJNIEnv->GetMethodID(classDisplayMetrics, "<init>", "()V");
|
||||||
|
jobject objectDisplayMetrics = lJNIEnv->NewObject(classDisplayMetrics, initDisplayMetrics);
|
||||||
|
|
||||||
|
jmethodID methodGetWindowManager = lJNIEnv->GetMethodID(classActivity, "getWindowManager", "()Landroid/view/WindowManager;");
|
||||||
|
jobject objectWindowManager = lJNIEnv->CallObjectMethod(objectActivity, methodGetWindowManager);
|
||||||
|
|
||||||
|
jclass classWindowManager = lJNIEnv->FindClass("android/view/WindowManager");
|
||||||
|
jmethodID methodGetDefaultDisplay = lJNIEnv->GetMethodID(classWindowManager, "getDefaultDisplay", "()Landroid/view/Display;");
|
||||||
|
jobject objectDisplay = lJNIEnv->CallObjectMethod(objectWindowManager, methodGetDefaultDisplay);
|
||||||
|
|
||||||
|
jclass classDisplay = lJNIEnv->FindClass("android/view/Display");
|
||||||
|
jmethodID methodGetMetrics = lJNIEnv->GetMethodID(classDisplay, "getMetrics", "(Landroid/util/DisplayMetrics;)V");
|
||||||
|
lJNIEnv->CallVoidMethod(objectDisplay, methodGetMetrics, objectDisplayMetrics);
|
||||||
|
|
||||||
|
jfieldID fieldWidthPixels = lJNIEnv->GetFieldID(classDisplayMetrics, "widthPixels", "I");
|
||||||
|
jfieldID fieldHeightPixels = lJNIEnv->GetFieldID(classDisplayMetrics, "heightPixels", "I");
|
||||||
|
|
||||||
|
*width = lJNIEnv->GetIntField(objectDisplayMetrics, fieldWidthPixels);
|
||||||
|
*height = lJNIEnv->GetIntField(objectDisplayMetrics, fieldHeightPixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static void onStart(ANativeActivity* activity)
|
static void onStart(ANativeActivity* activity)
|
||||||
{
|
{
|
||||||
|
@ -132,11 +201,14 @@ static void onResume(ANativeActivity* activity)
|
||||||
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
||||||
sf::Lock lock(states->mutex);
|
sf::Lock lock(states->mutex);
|
||||||
|
|
||||||
|
if (states->fullscreen)
|
||||||
|
goToFullscreenMode(activity);
|
||||||
|
|
||||||
// Send an event to warn people the activity has been resumed
|
// Send an event to warn people the activity has been resumed
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::MouseEntered;
|
event.type = sf::Event::MouseEntered;
|
||||||
|
|
||||||
states->pendingEvents.push_back(event);
|
states->forwardEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,7 +223,7 @@ static void onPause(ANativeActivity* activity)
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::MouseLeft;
|
event.type = sf::Event::MouseLeft;
|
||||||
|
|
||||||
states->pendingEvents.push_back(event);
|
states->forwardEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,7 +250,7 @@ static void onDestroy(ANativeActivity* activity)
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::Closed;
|
event.type = sf::Event::Closed;
|
||||||
|
|
||||||
states->pendingEvents.push_back(event);
|
states->forwardEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +291,7 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind
|
||||||
// Notify SFML mechanism
|
// Notify SFML mechanism
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::GainedFocus;
|
event.type = sf::Event::GainedFocus;
|
||||||
states->pendingEvents.push_back(event);
|
states->forwardEvent(event);
|
||||||
|
|
||||||
// Wait for the event to be taken into account by SFML
|
// Wait for the event to be taken into account by SFML
|
||||||
states->updated = false;
|
states->updated = false;
|
||||||
|
@ -244,7 +316,7 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi
|
||||||
// Notify SFML mechanism
|
// Notify SFML mechanism
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::LostFocus;
|
event.type = sf::Event::LostFocus;
|
||||||
states->pendingEvents.push_back(event);
|
states->forwardEvent(event);
|
||||||
|
|
||||||
// Wait for the event to be taken into account by SFML
|
// Wait for the event to be taken into account by SFML
|
||||||
states->updated = false;
|
states->updated = false;
|
||||||
|
@ -320,7 +392,7 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
|
||||||
event.size.width = ANativeWindow_getWidth(states->window);
|
event.size.width = ANativeWindow_getWidth(states->window);
|
||||||
event.size.height = ANativeWindow_getHeight(states->window);
|
event.size.height = ANativeWindow_getHeight(states->window);
|
||||||
|
|
||||||
states->pendingEvents.push_back(event);
|
states->forwardEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -345,14 +417,6 @@ static void onLowMemory(ANativeActivity* activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
int dummyProcessEvent(int fd, int events, void* data)
|
|
||||||
{
|
|
||||||
// Do nothing
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
|
void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
|
||||||
{
|
{
|
||||||
|
@ -370,14 +434,10 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
|
||||||
for (unsigned int i = 0; i < sf::Mouse::ButtonCount; i++)
|
for (unsigned int i = 0; i < sf::Mouse::ButtonCount; i++)
|
||||||
states->isButtonPressed[i] = false;
|
states->isButtonPressed[i] = false;
|
||||||
|
|
||||||
states->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
states->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
|
||||||
// As the input queue will be created before the SFML window, we need to use
|
if (savedState != NULL)
|
||||||
// this dummy function that will be replaced later by the first created
|
{
|
||||||
// SFML window
|
|
||||||
states->processEvent = dummyProcessEvent;
|
|
||||||
|
|
||||||
if (savedState != NULL) {
|
|
||||||
states->savedState = malloc(savedStateSize);
|
states->savedState = malloc(savedStateSize);
|
||||||
states->savedStateSize = savedStateSize;
|
states->savedStateSize = savedStateSize;
|
||||||
memcpy(states->savedState, savedState, savedStateSize);
|
memcpy(states->savedState, savedState, savedStateSize);
|
||||||
|
@ -421,38 +481,14 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
|
||||||
ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON,
|
ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON,
|
||||||
AWINDOW_FLAG_KEEP_SCREEN_ON);
|
AWINDOW_FLAG_KEEP_SCREEN_ON);
|
||||||
|
|
||||||
// Hide the status bar
|
|
||||||
ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN,
|
|
||||||
AWINDOW_FLAG_FULLSCREEN);
|
|
||||||
|
|
||||||
// Hide the navigation bar
|
|
||||||
JavaVM* lJavaVM = activity->vm;
|
|
||||||
JNIEnv* lJNIEnv = activity->env;
|
|
||||||
|
|
||||||
jobject objectActivity = activity->clazz;
|
|
||||||
jclass classActivity = lJNIEnv->GetObjectClass(objectActivity);
|
|
||||||
|
|
||||||
jmethodID methodGetWindow = lJNIEnv->GetMethodID(classActivity, "getWindow", "()Landroid/view/Window;");
|
|
||||||
jobject objectWindow = lJNIEnv->CallObjectMethod(objectActivity, methodGetWindow);
|
|
||||||
|
|
||||||
jclass classWindow = lJNIEnv->FindClass("android/view/Window");
|
|
||||||
jmethodID methodGetDecorView = lJNIEnv->GetMethodID(classWindow, "getDecorView", "()Landroid/view/View;");
|
|
||||||
jobject objectDecorView = lJNIEnv->CallObjectMethod(objectWindow, methodGetDecorView);
|
|
||||||
|
|
||||||
jclass classView = lJNIEnv->FindClass("android/view/View");
|
|
||||||
|
|
||||||
jfieldID FieldSYSTEM_UI_FLAG_HIDE_NAVIGATION = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_HIDE_NAVIGATION", "I");
|
|
||||||
jint SYSTEM_UI_FLAG_HIDE_NAVIGATION = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_HIDE_NAVIGATION);
|
|
||||||
|
|
||||||
jfieldID FieldSYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_FULLSCREEN", "I");
|
|
||||||
jint SYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_FULLSCREEN);
|
|
||||||
|
|
||||||
jmethodID methodsetSystemUiVisibility = lJNIEnv->GetMethodID(classView, "setSystemUiVisibility", "(I)V");
|
|
||||||
lJNIEnv->CallVoidMethod(objectDecorView, methodsetSystemUiVisibility, SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_FULLSCREEN);
|
|
||||||
|
|
||||||
// Initialize the display
|
// Initialize the display
|
||||||
eglInitialize(states->display, NULL, NULL);
|
eglInitialize(states->display, NULL, NULL);
|
||||||
|
|
||||||
|
getScreenSizeInPixels(activity, &states->screenSize.x, &states->screenSize.y);
|
||||||
|
|
||||||
|
// Redirect error messages to logcat
|
||||||
|
sf::err().rdbuf(&states->logcat);
|
||||||
|
|
||||||
// Launch the main thread
|
// Launch the main thread
|
||||||
sf::Thread* thread = new sf::Thread(sf::priv::main, states);
|
sf::Thread* thread = new sf::Thread(sf::priv::main, states);
|
||||||
thread->launch();
|
thread->launch();
|
||||||
|
|
|
@ -28,6 +28,29 @@
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/System/Android/Activity.hpp>
|
#include <SFML/System/Android/Activity.hpp>
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "sfml-error", __VA_ARGS__))
|
||||||
|
|
||||||
|
LogcatStream::LogcatStream() :
|
||||||
|
std::streambuf()
|
||||||
|
{
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streambuf::int_type LogcatStream::overflow (std::streambuf::int_type c)
|
||||||
|
{
|
||||||
|
if (c == "\n"[0])
|
||||||
|
{
|
||||||
|
m_message.push_back(c);
|
||||||
|
LOGE(m_message.c_str());
|
||||||
|
m_message.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_message.push_back(c);
|
||||||
|
|
||||||
|
return traits_type::not_eof(c);
|
||||||
|
}
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,7 +36,19 @@
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
class SFML_SYSTEM_API LogcatStream : public std::streambuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LogcatStream();
|
||||||
|
|
||||||
|
std::streambuf::int_type overflow (std::streambuf::int_type c);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_message;
|
||||||
|
};
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
@ -59,7 +71,7 @@ struct ActivityStates
|
||||||
|
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
|
|
||||||
std::vector<Event> pendingEvents;
|
void (*forwardEvent)(const Event& event);
|
||||||
int (*processEvent)(int fd, int events, void* data);
|
int (*processEvent)(int fd, int events, void* data);
|
||||||
|
|
||||||
std::map<int, Vector2i> touchEvents;
|
std::map<int, Vector2i> touchEvents;
|
||||||
|
@ -68,10 +80,16 @@ struct ActivityStates
|
||||||
|
|
||||||
bool mainOver;
|
bool mainOver;
|
||||||
|
|
||||||
|
Vector2i screenSize;
|
||||||
|
|
||||||
bool initialized;
|
bool initialized;
|
||||||
bool terminated;
|
bool terminated;
|
||||||
|
|
||||||
|
bool fullscreen;
|
||||||
|
|
||||||
bool updated;
|
bool updated;
|
||||||
|
|
||||||
|
LogcatStream logcat;
|
||||||
};
|
};
|
||||||
|
|
||||||
SFML_SYSTEM_API ActivityStates* getActivity(ActivityStates* initializedStates=NULL, bool reset=false);
|
SFML_SYSTEM_API ActivityStates* getActivity(ActivityStates* initializedStates=NULL, bool reset=false);
|
||||||
|
|
|
@ -90,7 +90,7 @@ if(SFML_OS_WINDOWS)
|
||||||
list(APPEND SYSTEM_EXT_LIBS winmm)
|
list(APPEND SYSTEM_EXT_LIBS winmm)
|
||||||
endif()
|
endif()
|
||||||
if(SFML_OS_ANDROID)
|
if(SFML_OS_ANDROID)
|
||||||
list(APPEND SYSTEM_EXT_LIBS android)
|
list(APPEND SYSTEM_EXT_LIBS android log)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# define the sfml-system target
|
# define the sfml-system target
|
||||||
|
|
|
@ -55,20 +55,7 @@ VideoMode VideoModeImpl::getDesktopMode()
|
||||||
priv::ActivityStates* states = priv::getActivity(NULL);
|
priv::ActivityStates* states = priv::getActivity(NULL);
|
||||||
Lock lock(states->mutex);
|
Lock lock(states->mutex);
|
||||||
|
|
||||||
// Wait for a window if there's none
|
return VideoMode(states->screenSize.x, states->screenSize.y);
|
||||||
while (!states->window)
|
|
||||||
{
|
|
||||||
states->mutex.unlock();
|
|
||||||
sleep(milliseconds(10));
|
|
||||||
states->mutex.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get size from the window
|
|
||||||
Vector2i size;
|
|
||||||
size.x = ANativeWindow_getWidth(states->window);
|
|
||||||
size.y = ANativeWindow_getHeight(states->window);
|
|
||||||
|
|
||||||
return VideoMode(size.x, size.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
|
@ -44,24 +44,36 @@ namespace sf
|
||||||
{
|
{
|
||||||
namespace priv
|
namespace priv
|
||||||
{
|
{
|
||||||
|
WindowImplAndroid* WindowImplAndroid::singleInstance = NULL;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
WindowImplAndroid::WindowImplAndroid(WindowHandle handle)
|
WindowImplAndroid::WindowImplAndroid(WindowHandle handle)
|
||||||
|
: m_size(0, 0)
|
||||||
|
, m_windowBeingCreated(false)
|
||||||
|
, m_windowBeingDestroyed(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsigned long style, const ContextSettings& settings)
|
WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsigned long style, const ContextSettings& settings)
|
||||||
|
: m_size(mode.width, mode.height)
|
||||||
|
, m_windowBeingCreated(false)
|
||||||
|
, m_windowBeingDestroyed(false)
|
||||||
{
|
{
|
||||||
ActivityStates* states = getActivity(NULL);
|
ActivityStates* states = getActivity(NULL);
|
||||||
Lock lock(states->mutex);
|
Lock lock(states->mutex);
|
||||||
|
|
||||||
// Replace our dummy process event function with the actual one
|
if (style& Style::Fullscreen)
|
||||||
AInputQueue_detachLooper(states->inputQueue);
|
states->fullscreen = true;
|
||||||
AInputQueue_attachLooper(states->inputQueue, states->looper, 1, processEvent, NULL);
|
|
||||||
|
|
||||||
// Register the actual process event function so it can be set automatically later by the OS
|
WindowImplAndroid::singleInstance = this;
|
||||||
|
states->forwardEvent = forwardEvent;
|
||||||
|
|
||||||
|
// Register process event callback
|
||||||
states->processEvent = processEvent;
|
states->processEvent = processEvent;
|
||||||
|
|
||||||
|
states->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,30 +96,25 @@ WindowHandle WindowImplAndroid::getSystemHandle() const
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplAndroid::processEvents()
|
void WindowImplAndroid::processEvents()
|
||||||
{
|
{
|
||||||
ActivityStates* states = getActivity(NULL);
|
|
||||||
Lock lock(states->mutex);
|
|
||||||
|
|
||||||
// Process incoming OS events
|
// Process incoming OS events
|
||||||
ALooper_pollAll(0, NULL, NULL, NULL);
|
ALooper_pollAll(0, NULL, NULL, NULL);
|
||||||
|
|
||||||
while (!states->pendingEvents.empty())
|
ActivityStates* states = getActivity(NULL);
|
||||||
|
sf::Lock lock(states->mutex);
|
||||||
|
|
||||||
|
if (m_windowBeingCreated)
|
||||||
{
|
{
|
||||||
Event tempEvent = states->pendingEvents.back();
|
states->context->createSurface(states->window);
|
||||||
states->pendingEvents.pop_back();
|
m_windowBeingCreated = false;
|
||||||
|
|
||||||
if (tempEvent.type == Event::GainedFocus)
|
|
||||||
{
|
|
||||||
states->context->createSurface(states->window);
|
|
||||||
states->updated = true;
|
|
||||||
}
|
|
||||||
else if (tempEvent.type == Event::LostFocus)
|
|
||||||
{
|
|
||||||
states->context->destroySurface();
|
|
||||||
states->updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pushEvent(tempEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_windowBeingDestroyed)
|
||||||
|
{
|
||||||
|
states->context->destroySurface();
|
||||||
|
m_windowBeingDestroyed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
states->updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,13 +136,7 @@ void WindowImplAndroid::setPosition(const Vector2i& position)
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector2u WindowImplAndroid::getSize() const
|
Vector2u WindowImplAndroid::getSize() const
|
||||||
{
|
{
|
||||||
ActivityStates* states = getActivity(NULL);
|
return m_size;
|
||||||
Lock lock(states->mutex);
|
|
||||||
|
|
||||||
int32_t width = ANativeWindow_getWidth(states->window);
|
|
||||||
int32_t height = ANativeWindow_getHeight(states->window);
|
|
||||||
|
|
||||||
return Vector2u(static_cast<unsigned int>(width), static_cast<unsigned int>(height));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,6 +181,26 @@ void WindowImplAndroid::setKeyRepeatEnabled(bool enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplAndroid::forwardEvent(const Event& event)
|
||||||
|
{
|
||||||
|
ActivityStates* states = getActivity(NULL);
|
||||||
|
|
||||||
|
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_windowBeingCreated = true;
|
||||||
|
}
|
||||||
|
else if (event.type == Event::LostFocus)
|
||||||
|
{
|
||||||
|
WindowImplAndroid::singleInstance->m_windowBeingDestroyed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowImplAndroid::singleInstance->pushEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||||
{
|
{
|
||||||
|
@ -192,7 +213,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||||
{
|
{
|
||||||
if (AInputQueue_preDispatchEvent(states->inputQueue, _event))
|
if (AInputQueue_preDispatchEvent(states->inputQueue, _event))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
int32_t handled = 0;
|
int32_t handled = 0;
|
||||||
|
|
||||||
int32_t type = AInputEvent_getType(_event);
|
int32_t type = AInputEvent_getType(_event);
|
||||||
|
@ -209,7 +230,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||||
else if (type == AINPUT_EVENT_TYPE_MOTION)
|
else if (type == AINPUT_EVENT_TYPE_MOTION)
|
||||||
{
|
{
|
||||||
int32_t action = AMotionEvent_getAction(_event);
|
int32_t action = AMotionEvent_getAction(_event);
|
||||||
|
|
||||||
switch (action & AMOTION_EVENT_ACTION_MASK)
|
switch (action & AMOTION_EVENT_ACTION_MASK)
|
||||||
{
|
{
|
||||||
case AMOTION_EVENT_ACTION_SCROLL:
|
case AMOTION_EVENT_ACTION_SCROLL:
|
||||||
|
@ -217,7 +238,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||||
processScrollEvent(_event, states);
|
processScrollEvent(_event, states);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMOTION_EVENT_ACTION_HOVER_MOVE:
|
case AMOTION_EVENT_ACTION_HOVER_MOVE:
|
||||||
case AMOTION_EVENT_ACTION_MOVE:
|
case AMOTION_EVENT_ACTION_MOVE:
|
||||||
{
|
{
|
||||||
|
@ -285,7 +306,7 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates*
|
||||||
jfloat yPrecision = AMotionEvent_getYPrecision(_event);
|
jfloat yPrecision = AMotionEvent_getYPrecision(_event);
|
||||||
jint deviceId = AInputEvent_getDeviceId(_event);
|
jint deviceId = AInputEvent_getDeviceId(_event);
|
||||||
jint edgeFlags = AMotionEvent_getEdgeFlags(_event);
|
jint edgeFlags = AMotionEvent_getEdgeFlags(_event);
|
||||||
|
|
||||||
// Create the MotionEvent object in java trough its static constructor obtain()
|
// Create the MotionEvent object in java trough its static constructor obtain()
|
||||||
jclass ClassMotionEvent = lJNIEnv->FindClass("android/view/MotionEvent");
|
jclass ClassMotionEvent = lJNIEnv->FindClass("android/view/MotionEvent");
|
||||||
jmethodID StaticMethodObtain = lJNIEnv->GetStaticMethodID(ClassMotionEvent, "obtain", "(JJIFFFFIFFII)Landroid/view/MotionEvent;");
|
jmethodID StaticMethodObtain = lJNIEnv->GetStaticMethodID(ClassMotionEvent, "obtain", "(JJIFFFFIFFII)Landroid/view/MotionEvent;");
|
||||||
|
@ -294,15 +315,15 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates*
|
||||||
// Call its getAxisValue() method to get the delta value of our wheel move event
|
// Call its getAxisValue() method to get the delta value of our wheel move event
|
||||||
jmethodID MethodGetAxisValue = lJNIEnv->GetMethodID(ClassMotionEvent, "getAxisValue", "(I)F");
|
jmethodID MethodGetAxisValue = lJNIEnv->GetMethodID(ClassMotionEvent, "getAxisValue", "(I)F");
|
||||||
jfloat delta = lJNIEnv->CallFloatMethod(ObjectMotionEvent, MethodGetAxisValue, 0x00000001);
|
jfloat delta = lJNIEnv->CallFloatMethod(ObjectMotionEvent, MethodGetAxisValue, 0x00000001);
|
||||||
|
|
||||||
// Create and send our mouse wheel event
|
// Create and send our mouse wheel event
|
||||||
Event event;
|
Event event;
|
||||||
event.type = Event::MouseWheelMoved;
|
event.type = Event::MouseWheelMoved;
|
||||||
event.mouseWheel.delta = static_cast<double>(delta);
|
event.mouseWheel.delta = static_cast<double>(delta);
|
||||||
event.mouseWheel.x = AMotionEvent_getX(_event, 0);
|
event.mouseWheel.x = AMotionEvent_getX(_event, 0);
|
||||||
event.mouseWheel.y = AMotionEvent_getY(_event, 0);
|
event.mouseWheel.y = AMotionEvent_getY(_event, 0);
|
||||||
|
|
||||||
states->pendingEvents.push_back(event);
|
forwardEvent(event);
|
||||||
|
|
||||||
// Dettach this thread from the JVM
|
// Dettach this thread from the JVM
|
||||||
lJavaVM->DetachCurrentThread();
|
lJavaVM->DetachCurrentThread();
|
||||||
|
@ -314,7 +335,7 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
||||||
{
|
{
|
||||||
int32_t device = AInputEvent_getSource(_event);
|
int32_t device = AInputEvent_getSource(_event);
|
||||||
int32_t action = AKeyEvent_getAction(_event);
|
int32_t action = AKeyEvent_getAction(_event);
|
||||||
|
|
||||||
int32_t key = AKeyEvent_getKeyCode(_event);
|
int32_t key = AKeyEvent_getKeyCode(_event);
|
||||||
int32_t metakey = AKeyEvent_getMetaState(_event);
|
int32_t metakey = AKeyEvent_getMetaState(_event);
|
||||||
|
|
||||||
|
@ -325,14 +346,14 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
||||||
event.key.control = false;
|
event.key.control = false;
|
||||||
event.key.shift = metakey & AMETA_SHIFT_ON;
|
event.key.shift = metakey & AMETA_SHIFT_ON;
|
||||||
|
|
||||||
states->pendingEvents.push_back(event);
|
forwardEvent(event);
|
||||||
|
|
||||||
if (int unicode = getUnicode(_event))
|
if (int unicode = getUnicode(_event))
|
||||||
{
|
{
|
||||||
Event event;
|
Event event;
|
||||||
event.type = Event::TextEntered;
|
event.type = Event::TextEntered;
|
||||||
event.text.unicode = unicode;
|
event.text.unicode = unicode;
|
||||||
states->pendingEvents.push_back(event);
|
forwardEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,26 +365,26 @@ void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates*
|
||||||
int32_t action = AMotionEvent_getAction(_event);
|
int32_t action = AMotionEvent_getAction(_event);
|
||||||
|
|
||||||
Event event;
|
Event event;
|
||||||
|
|
||||||
if (device == AINPUT_SOURCE_MOUSE)
|
if (device == AINPUT_SOURCE_MOUSE)
|
||||||
event.type = Event::MouseMoved;
|
event.type = Event::MouseMoved;
|
||||||
else if (device == AINPUT_SOURCE_TOUCHSCREEN)
|
else if (device == AINPUT_SOURCE_TOUCHSCREEN)
|
||||||
event.type = Event::TouchMoved;
|
event.type = Event::TouchMoved;
|
||||||
|
|
||||||
int pointerCount = AMotionEvent_getPointerCount(_event);
|
int pointerCount = AMotionEvent_getPointerCount(_event);
|
||||||
|
|
||||||
for (int p = 0; p < pointerCount; p++)
|
for (int p = 0; p < pointerCount; p++)
|
||||||
{
|
{
|
||||||
int id = AMotionEvent_getPointerId(_event, p);
|
int id = AMotionEvent_getPointerId(_event, p);
|
||||||
|
|
||||||
float x = AMotionEvent_getX(_event, p);
|
float x = AMotionEvent_getX(_event, p);
|
||||||
float y = AMotionEvent_getY(_event, p);
|
float y = AMotionEvent_getY(_event, p);
|
||||||
|
|
||||||
if (device == AINPUT_SOURCE_MOUSE)
|
if (device == AINPUT_SOURCE_MOUSE)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
@ -374,11 +395,11 @@ void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates*
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
states->pendingEvents.push_back(event);
|
forwardEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,13 +409,13 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac
|
||||||
{
|
{
|
||||||
int32_t device = AInputEvent_getSource(_event);
|
int32_t device = AInputEvent_getSource(_event);
|
||||||
int32_t action = AMotionEvent_getAction(_event);
|
int32_t action = AMotionEvent_getAction(_event);
|
||||||
|
|
||||||
int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||||
int id = AMotionEvent_getPointerId(_event, index);
|
int id = AMotionEvent_getPointerId(_event, index);
|
||||||
|
|
||||||
float x = AMotionEvent_getX(_event, index);
|
float x = AMotionEvent_getX(_event, index);
|
||||||
float y = AMotionEvent_getY(_event, index);
|
float y = AMotionEvent_getY(_event, index);
|
||||||
|
|
||||||
Event event;
|
Event event;
|
||||||
|
|
||||||
if (isDown)
|
if (isDown)
|
||||||
|
@ -405,7 +426,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac
|
||||||
event.mouseButton.button = static_cast<Mouse::Button>(id);
|
event.mouseButton.button = static_cast<Mouse::Button>(id);
|
||||||
event.mouseButton.x = x;
|
event.mouseButton.x = x;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -415,7 +436,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,7 +448,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac
|
||||||
event.mouseButton.button = static_cast<Mouse::Button>(id);
|
event.mouseButton.button = static_cast<Mouse::Button>(id);
|
||||||
event.mouseButton.x = x;
|
event.mouseButton.x = x;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -437,12 +458,12 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac
|
||||||
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.erase(id);
|
states->touchEvents.erase(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
states->pendingEvents.push_back(event);
|
forwardEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,9 @@ public :
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void setKeyRepeatEnabled(bool enabled);
|
virtual void setKeyRepeatEnabled(bool enabled);
|
||||||
|
|
||||||
|
static void forwardEvent(const Event& event);
|
||||||
|
static WindowImplAndroid* singleInstance;
|
||||||
|
|
||||||
protected :
|
protected :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -190,7 +193,7 @@ private:
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static Keyboard::Key androidKeyToSF(int32_t key);
|
static Keyboard::Key androidKeyToSF(int32_t key);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get unicode decoded from the input event
|
/// \brief Get unicode decoded from the input event
|
||||||
///
|
///
|
||||||
|
@ -200,6 +203,10 @@ private:
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static int getUnicode(AInputEvent* event);
|
static int getUnicode(AInputEvent* event);
|
||||||
|
|
||||||
|
Vector2u m_size;
|
||||||
|
bool m_windowBeingCreated;
|
||||||
|
bool m_windowBeingDestroyed;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
|
@ -109,9 +109,16 @@ void Window::create(VideoMode mode, const String& title, Uint32 style, const Con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check validity of style
|
// Check validity of style according to the underlying platform
|
||||||
if ((style & Style::Close) || (style & Style::Resize))
|
#if defined(SFML_SYSTEM_IOS) || defined(SFML_SYSTEM_ANDROID)
|
||||||
style |= Style::Titlebar;
|
if (style & Style::Fullscreen)
|
||||||
|
style &= ~Style::Titlebar;
|
||||||
|
else
|
||||||
|
style |= Style::Titlebar;
|
||||||
|
#else
|
||||||
|
if ((style & Style::Close) || (style & Style::Resize))
|
||||||
|
style |= Style::Titlebar;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Recreate the window implementation
|
// Recreate the window implementation
|
||||||
m_impl = priv::WindowImpl::create(mode, title, style, settings);
|
m_impl = priv::WindowImpl::create(mode, title, style, settings);
|
||||||
|
|
Loading…
Reference in a new issue