From fb81ddfdcbc3419160d9686dce6fd5eefeb35772 Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Thu, 26 Jun 2014 04:56:06 +0200 Subject: [PATCH 1/9] [Android] VideoMode::getDesktopMode() returns the physical scren size in pixels --- src/SFML/Main/MainAndroid.cpp | 40 +++++++++++++++++++++++ src/SFML/System/Android/Activity.hpp | 2 ++ src/SFML/Window/Android/VideoModeImpl.cpp | 15 +-------- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index 08e232ab..83fe044e 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -119,6 +119,44 @@ void* main(ActivityStates* states) } // namespace sf +//////////////////////////////////////////////////////////// + +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, "", "()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) { @@ -453,6 +491,8 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_ // Initialize the display eglInitialize(states->display, NULL, NULL); + getScreenSizeInPixels(activity, &states->screenSize.x, &states->screenSize.y); + // Launch the main thread sf::Thread* thread = new sf::Thread(sf::priv::main, states); thread->launch(); diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index e5c96786..afd256b6 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -68,6 +68,8 @@ struct ActivityStates bool mainOver; + Vector2i screenSize; + bool initialized; bool terminated; diff --git a/src/SFML/Window/Android/VideoModeImpl.cpp b/src/SFML/Window/Android/VideoModeImpl.cpp index 8082c9ce..d9c171c1 100644 --- a/src/SFML/Window/Android/VideoModeImpl.cpp +++ b/src/SFML/Window/Android/VideoModeImpl.cpp @@ -55,20 +55,7 @@ VideoMode VideoModeImpl::getDesktopMode() priv::ActivityStates* states = priv::getActivity(NULL); Lock lock(states->mutex); - // Wait for a window if there's none - 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); + return VideoMode(states->screenSize.x, states->screenSize.y); } } // namespace priv From cf526872038c8f26a773732ae7b5b2c29a695d9d Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Thu, 26 Jun 2014 05:15:25 +0200 Subject: [PATCH 2/9] [Android] onCreate nows waits for sf::Window to be created --- src/SFML/Main/MainAndroid.cpp | 24 +++---------------- src/SFML/Window/Android/WindowImplAndroid.cpp | 22 ++++++++--------- src/SFML/Window/Android/WindowImplAndroid.hpp | 2 ++ 3 files changed, 15 insertions(+), 33 deletions(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index 83fe044e..e98444b1 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -94,12 +94,6 @@ void* main(ActivityStates* states) // Initialize the thread before giving the hand initializeMain(states); - { - Lock lock(states->mutex); - - states->initialized = true; - } - sleep(seconds(0.5)); ::main(0, NULL); @@ -383,14 +377,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) { @@ -408,14 +394,10 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_ for (unsigned int i = 0; i < sf::Mouse::ButtonCount; i++) 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 - // this dummy function that will be replaced later by the first created - // SFML window - states->processEvent = dummyProcessEvent; - - if (savedState != NULL) { + if (savedState != NULL) + { states->savedState = malloc(savedStateSize); states->savedStateSize = savedStateSize; memcpy(states->savedState, savedState, savedStateSize); diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index da78bc7c..bd22bf56 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -46,22 +46,22 @@ namespace priv { //////////////////////////////////////////////////////////// WindowImplAndroid::WindowImplAndroid(WindowHandle handle) +: m_size(0, 0) { } //////////////////////////////////////////////////////////// WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsigned long style, const ContextSettings& settings) +: m_size(mode.width, mode.height) { ActivityStates* states = getActivity(NULL); Lock lock(states->mutex); - // Replace our dummy process event function with the actual one - AInputQueue_detachLooper(states->inputQueue); - 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 + // Register process event callback states->processEvent = processEvent; + + states->initialized = true; } @@ -98,6 +98,10 @@ void WindowImplAndroid::processEvents() if (tempEvent.type == Event::GainedFocus) { states->context->createSurface(states->window); + + m_size.x = ANativeWindow_getWidth(states->window); + m_size.y = ANativeWindow_getHeight(states->window); + states->updated = true; } else if (tempEvent.type == Event::LostFocus) @@ -129,13 +133,7 @@ void WindowImplAndroid::setPosition(const Vector2i& position) //////////////////////////////////////////////////////////// Vector2u WindowImplAndroid::getSize() const { - ActivityStates* states = getActivity(NULL); - Lock lock(states->mutex); - - int32_t width = ANativeWindow_getWidth(states->window); - int32_t height = ANativeWindow_getHeight(states->window); - - return Vector2u(static_cast(width), static_cast(height)); + return m_size; } diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index d1249a2e..16a24538 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -200,6 +200,8 @@ private: /// //////////////////////////////////////////////////////////// static int getUnicode(AInputEvent* event); + + Vector2u m_size; }; } // namespace priv From 73008293ba32c00dfd791aaca2524745221a6b9a Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Thu, 26 Jun 2014 05:21:28 +0200 Subject: [PATCH 3/9] Window style constraints are handled differently on mobile OSes --- src/SFML/Window/Window.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp index 6fd7cb6b..a3a94ed6 100644 --- a/src/SFML/Window/Window.cpp +++ b/src/SFML/Window/Window.cpp @@ -109,9 +109,13 @@ void Window::create(VideoMode mode, const String& title, Uint32 style, const Con } } - // Check validity of style - if ((style & Style::Close) || (style & Style::Resize)) - style |= Style::Titlebar; + // Check validity of style according to the underlying platform + #if defined(SFML_SYSTEM_IOS) || defined(SFML_SYSTEM_ANDROID) + style& Style::Fullscreen ? style &= ~Style::Titlebar : style |= Style::Titlebar; + #else + if ((style & Style::Close) || (style & Style::Resize)) + style |= Style::Titlebar; + #endif // Recreate the window implementation m_impl = priv::WindowImpl::create(mode, title, style, settings); From 57ca180d8de4c373fa3baaa33c4cee87b55b2fcb Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Thu, 26 Jun 2014 07:32:44 +0200 Subject: [PATCH 4/9] [Android] Hide status and navigation bar only if the fullscreen flag is on --- src/SFML/Main/MainAndroid.cpp | 68 +++++++++++-------- src/SFML/System/Android/Activity.hpp | 2 + src/SFML/Window/Android/WindowImplAndroid.cpp | 32 ++++----- src/SFML/Window/Android/WindowImplAndroid.hpp | 2 +- 4 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index e98444b1..5da2d39d 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -113,6 +113,42 @@ void* main(ActivityStates* states) } // 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) @@ -164,6 +200,9 @@ static void onResume(ANativeActivity* activity) sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); sf::Lock lock(states->mutex); + if (states->fullscreen) + goToFullscreenMode(activity); + // Send an event to warn people the activity has been resumed sf::Event event; event.type = sf::Event::MouseEntered; @@ -441,35 +480,6 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_ ANativeActivity_setWindowFlags(activity, 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 eglInitialize(states->display, NULL, NULL); diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index afd256b6..ea7d58d6 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -73,6 +73,8 @@ struct ActivityStates bool initialized; bool terminated; + bool fullscreen; + bool updated; }; diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index bd22bf56..8e2e2bf7 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -190,7 +190,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) { if (AInputQueue_preDispatchEvent(states->inputQueue, _event)) return 1; - + int32_t handled = 0; int32_t type = AInputEvent_getType(_event); @@ -207,7 +207,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) else if (type == AINPUT_EVENT_TYPE_MOTION) { int32_t action = AMotionEvent_getAction(_event); - + switch (action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_SCROLL: @@ -215,7 +215,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) processScrollEvent(_event, states); break; } - + case AMOTION_EVENT_ACTION_HOVER_MOVE: case AMOTION_EVENT_ACTION_MOVE: { @@ -283,7 +283,7 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* jfloat yPrecision = AMotionEvent_getYPrecision(_event); jint deviceId = AInputEvent_getDeviceId(_event); jint edgeFlags = AMotionEvent_getEdgeFlags(_event); - + // Create the MotionEvent object in java trough its static constructor obtain() jclass ClassMotionEvent = lJNIEnv->FindClass("android/view/MotionEvent"); jmethodID StaticMethodObtain = lJNIEnv->GetStaticMethodID(ClassMotionEvent, "obtain", "(JJIFFFFIFFII)Landroid/view/MotionEvent;"); @@ -312,7 +312,7 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta { int32_t device = AInputEvent_getSource(_event); int32_t action = AKeyEvent_getAction(_event); - + int32_t key = AKeyEvent_getKeyCode(_event); int32_t metakey = AKeyEvent_getMetaState(_event); @@ -342,26 +342,26 @@ void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* int32_t action = AMotionEvent_getAction(_event); Event event; - + if (device == AINPUT_SOURCE_MOUSE) event.type = Event::MouseMoved; else if (device == AINPUT_SOURCE_TOUCHSCREEN) event.type = Event::TouchMoved; int pointerCount = AMotionEvent_getPointerCount(_event); - + for (int p = 0; p < pointerCount; p++) { int id = AMotionEvent_getPointerId(_event, p); float x = AMotionEvent_getX(_event, p); float y = AMotionEvent_getY(_event, p); - + if (device == AINPUT_SOURCE_MOUSE) { event.mouseMove.x = x; event.mouseMove.y = y; - + states->mousePosition = Vector2i(event.mouseMove.x, event.mouseMove.y); } else if (device == AINPUT_SOURCE_TOUCHSCREEN) @@ -372,7 +372,7 @@ void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* event.touch.finger = id; event.touch.x = x; event.touch.y = y; - + states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); } @@ -386,13 +386,13 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac { int32_t device = AInputEvent_getSource(_event); int32_t action = AMotionEvent_getAction(_event); - + int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; int id = AMotionEvent_getPointerId(_event, index); float x = AMotionEvent_getX(_event, index); float y = AMotionEvent_getY(_event, index); - + Event event; if (isDown) @@ -403,7 +403,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac event.mouseButton.button = static_cast(id); event.mouseButton.x = x; event.mouseButton.y = y; - + if (id >= 0 && id < Mouse::ButtonCount) states->isButtonPressed[id] = true; } @@ -413,7 +413,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac event.touch.finger = id; event.touch.x = x; event.touch.y = y; - + states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); } } @@ -425,7 +425,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac event.mouseButton.button = static_cast(id); event.mouseButton.x = x; event.mouseButton.y = y; - + if (id >= 0 && id < Mouse::ButtonCount) states->isButtonPressed[id] = false; } @@ -435,7 +435,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac event.touch.finger = id; event.touch.x = x; event.touch.y = y; - + states->touchEvents.erase(id); } } diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index 16a24538..fb7b8536 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -190,7 +190,7 @@ private: /// //////////////////////////////////////////////////////////// static Keyboard::Key androidKeyToSF(int32_t key); - + //////////////////////////////////////////////////////////// /// \brief Get unicode decoded from the input event /// From c462f7cd0ab7b877d34af32514cd5b5231b6184e Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Thu, 26 Jun 2014 07:33:03 +0200 Subject: [PATCH 5/9] [Android] Got rid of the unnecessary additional event container --- src/SFML/Main/MainAndroid.cpp | 16 ++-- src/SFML/System/Android/Activity.hpp | 2 +- src/SFML/Window/Android/WindowImplAndroid.cpp | 74 ++++++++++--------- src/SFML/Window/Android/WindowImplAndroid.hpp | 3 + 4 files changed, 51 insertions(+), 44 deletions(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index 5da2d39d..7399db16 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -207,7 +207,7 @@ static void onResume(ANativeActivity* activity) sf::Event event; event.type = sf::Event::MouseEntered; - states->pendingEvents.push_back(event); + states->forwardEvent(event); } @@ -222,7 +222,7 @@ static void onPause(ANativeActivity* activity) sf::Event event; event.type = sf::Event::MouseLeft; - states->pendingEvents.push_back(event); + states->forwardEvent(event); } @@ -249,7 +249,7 @@ static void onDestroy(ANativeActivity* activity) sf::Event event; event.type = sf::Event::Closed; - states->pendingEvents.push_back(event); + states->forwardEvent(event); } } @@ -288,12 +288,12 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind states->window = window; // Notify SFML mechanism + states->updated = false; sf::Event event; event.type = sf::Event::GainedFocus; - states->pendingEvents.push_back(event); + states->forwardEvent(event); // Wait for the event to be taken into account by SFML - states->updated = false; while(!states->updated) { states->mutex.unlock(); @@ -313,12 +313,12 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi states->window = NULL; // Notify SFML mechanism + states->updated = false; sf::Event event; event.type = sf::Event::LostFocus; - states->pendingEvents.push_back(event); + states->forwardEvent(event); // Wait for the event to be taken into account by SFML - states->updated = false; while(!states->updated) { states->mutex.unlock(); @@ -391,7 +391,7 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) event.size.width = ANativeWindow_getWidth(states->window); event.size.height = ANativeWindow_getHeight(states->window); - states->pendingEvents.push_back(event); + states->forwardEvent(event); } diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index ea7d58d6..572b1975 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -59,7 +59,7 @@ struct ActivityStates Mutex mutex; - std::vector pendingEvents; + void (*forwardEvent)(const Event& event); int (*processEvent)(int fd, int events, void* data); std::map touchEvents; diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index 8e2e2bf7..c15cd5d4 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -44,6 +44,8 @@ namespace sf { namespace priv { +WindowImplAndroid* WindowImplAndroid::singleInstance = NULL; + //////////////////////////////////////////////////////////// WindowImplAndroid::WindowImplAndroid(WindowHandle handle) : m_size(0, 0) @@ -58,6 +60,9 @@ WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsign ActivityStates* states = getActivity(NULL); Lock lock(states->mutex); + if (style& Style::Fullscreen) + states->fullscreen = true; + // Register process event callback states->processEvent = processEvent; @@ -84,34 +89,8 @@ WindowHandle WindowImplAndroid::getSystemHandle() const //////////////////////////////////////////////////////////// void WindowImplAndroid::processEvents() { - ActivityStates* states = getActivity(NULL); - Lock lock(states->mutex); - // Process incoming OS events ALooper_pollAll(0, NULL, NULL, NULL); - - while (!states->pendingEvents.empty()) - { - Event tempEvent = states->pendingEvents.back(); - states->pendingEvents.pop_back(); - - if (tempEvent.type == Event::GainedFocus) - { - states->context->createSurface(states->window); - - m_size.x = ANativeWindow_getWidth(states->window); - m_size.y = ANativeWindow_getHeight(states->window); - - states->updated = true; - } - else if (tempEvent.type == Event::LostFocus) - { - states->context->destroySurface(); - states->updated = true; - } - - pushEvent(tempEvent); - } } @@ -178,6 +157,31 @@ void WindowImplAndroid::setKeyRepeatEnabled(bool enabled) } +//////////////////////////////////////////////////////////// +void WindowImplAndroid::forwardEvent(const Event& event) +{ + ActivityStates* states = getActivity(NULL); + Lock lock(states->mutex); + + if (event.type == Event::GainedFocus) + { + states->context->createSurface(states->window); + + WindowImplAndroid::singleInstance->m_size.x = ANativeWindow_getWidth(states->window); + WindowImplAndroid::singleInstance->m_size.y = ANativeWindow_getHeight(states->window); + + states->updated = true; + } + else if (event.type == Event::LostFocus) + { + states->context->destroySurface(); + states->updated = true; + } + + WindowImplAndroid::singleInstance->pushEvent(event); +} + + //////////////////////////////////////////////////////////// int WindowImplAndroid::processEvent(int fd, int events, void* data) { @@ -292,15 +296,15 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* // Call its getAxisValue() method to get the delta value of our wheel move event jmethodID MethodGetAxisValue = lJNIEnv->GetMethodID(ClassMotionEvent, "getAxisValue", "(I)F"); jfloat delta = lJNIEnv->CallFloatMethod(ObjectMotionEvent, MethodGetAxisValue, 0x00000001); - + // Create and send our mouse wheel event Event event; event.type = Event::MouseWheelMoved; event.mouseWheel.delta = static_cast(delta); event.mouseWheel.x = AMotionEvent_getX(_event, 0); event.mouseWheel.y = AMotionEvent_getY(_event, 0); - - states->pendingEvents.push_back(event); + + forwardEvent(event); // Dettach this thread from the JVM lJavaVM->DetachCurrentThread(); @@ -323,14 +327,14 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta event.key.control = false; event.key.shift = metakey & AMETA_SHIFT_ON; - states->pendingEvents.push_back(event); + forwardEvent(event); if (int unicode = getUnicode(_event)) { Event event; event.type = Event::TextEntered; event.text.unicode = unicode; - states->pendingEvents.push_back(event); + forwardEvent(event); } } @@ -375,8 +379,8 @@ void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); } - - states->pendingEvents.push_back(event); + + forwardEvent(event); } } @@ -439,8 +443,8 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac states->touchEvents.erase(id); } } - - states->pendingEvents.push_back(event); + + forwardEvent(event); } diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index fb7b8536..5c8062e5 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -154,6 +154,9 @@ public : //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled); + static void forwardEvent(const Event& event); + static WindowImplAndroid* singleInstance; + protected : //////////////////////////////////////////////////////////// From dd6b54d0ebfc2ff20b6490fc9b3dfae87277d9a5 Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Thu, 26 Jun 2014 07:55:49 +0200 Subject: [PATCH 6/9] [Android] Forgot to add two lines to the previous commit --- src/SFML/Window/Android/WindowImplAndroid.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index c15cd5d4..ad5d8714 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -63,6 +63,9 @@ WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsign if (style& Style::Fullscreen) states->fullscreen = true; + WindowImplAndroid::singleInstance = this; + states->forwardEvent = forwardEvent; + // Register process event callback states->processEvent = processEvent; From f491e942973dd27177aa10e03772aa20433cd088 Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Tue, 8 Jul 2014 17:59:33 +0200 Subject: [PATCH 7/9] [Android] Redirect error messages to logcat by default --- src/SFML/Main/MainAndroid.cpp | 4 ++++ src/SFML/System/Android/Activity.cpp | 23 +++++++++++++++++++++++ src/SFML/System/Android/Activity.hpp | 14 ++++++++++++++ src/SFML/System/CMakeLists.txt | 2 +- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index 7399db16..27d75d74 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -485,6 +486,9 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_ getScreenSizeInPixels(activity, &states->screenSize.x, &states->screenSize.y); + // Redirect error messages to logcat + sf::err().rdbuf(&states->logcat); + // Launch the main thread sf::Thread* thread = new sf::Thread(sf::priv::main, states); thread->launch(); diff --git a/src/SFML/System/Android/Activity.cpp b/src/SFML/System/Android/Activity.cpp index 28655a35..b5ba35d2 100644 --- a/src/SFML/System/Android/Activity.cpp +++ b/src/SFML/System/Android/Activity.cpp @@ -28,6 +28,29 @@ // Headers //////////////////////////////////////////////////////////// #include +#include + +#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 { diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index 572b1975..bd6bbc9a 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -36,7 +36,19 @@ #include #include #include +#include +#include +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 { @@ -76,6 +88,8 @@ struct ActivityStates bool fullscreen; bool updated; + + LogcatStream logcat; }; SFML_SYSTEM_API ActivityStates* getActivity(ActivityStates* initializedStates=NULL, bool reset=false); diff --git a/src/SFML/System/CMakeLists.txt b/src/SFML/System/CMakeLists.txt index 080320a3..728cb52f 100644 --- a/src/SFML/System/CMakeLists.txt +++ b/src/SFML/System/CMakeLists.txt @@ -90,7 +90,7 @@ if(SFML_OS_WINDOWS) list(APPEND SYSTEM_EXT_LIBS winmm) endif() if(SFML_OS_ANDROID) - list(APPEND SYSTEM_EXT_LIBS android) + list(APPEND SYSTEM_EXT_LIBS android log) endif() # define the sfml-system target From 796c87295c0abdfed912ad2bdec878c744439f82 Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Thu, 24 Jul 2014 08:35:23 +0200 Subject: [PATCH 8/9] Improved readability of ?: operator --- src/SFML/Window/Window.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp index a3a94ed6..cd447b12 100644 --- a/src/SFML/Window/Window.cpp +++ b/src/SFML/Window/Window.cpp @@ -111,7 +111,10 @@ void Window::create(VideoMode mode, const String& title, Uint32 style, const Con // Check validity of style according to the underlying platform #if defined(SFML_SYSTEM_IOS) || defined(SFML_SYSTEM_ANDROID) - style& Style::Fullscreen ? style &= ~Style::Titlebar : 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; From f7561f5fa17ef538728e26c002c9f62c60f2dcb9 Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Thu, 24 Jul 2014 10:03:11 +0200 Subject: [PATCH 9/9] Fixed EGL surface not recreated in the right thread --- src/SFML/Main/MainAndroid.cpp | 4 +-- src/SFML/Window/Android/WindowImplAndroid.cpp | 30 ++++++++++++++----- src/SFML/Window/Android/WindowImplAndroid.hpp | 2 ++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index 27d75d74..67d88db8 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -289,12 +289,12 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind states->window = window; // Notify SFML mechanism - states->updated = false; sf::Event event; event.type = sf::Event::GainedFocus; states->forwardEvent(event); // Wait for the event to be taken into account by SFML + states->updated = false; while(!states->updated) { states->mutex.unlock(); @@ -314,12 +314,12 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi states->window = NULL; // Notify SFML mechanism - states->updated = false; sf::Event event; event.type = sf::Event::LostFocus; states->forwardEvent(event); // Wait for the event to be taken into account by SFML + states->updated = false; while(!states->updated) { states->mutex.unlock(); diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index ad5d8714..7a7a60b0 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -49,6 +49,8 @@ WindowImplAndroid* WindowImplAndroid::singleInstance = NULL; //////////////////////////////////////////////////////////// WindowImplAndroid::WindowImplAndroid(WindowHandle handle) : m_size(0, 0) +, m_windowBeingCreated(false) +, m_windowBeingDestroyed(false) { } @@ -56,6 +58,8 @@ WindowImplAndroid::WindowImplAndroid(WindowHandle handle) //////////////////////////////////////////////////////////// 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); Lock lock(states->mutex); @@ -94,6 +98,23 @@ void WindowImplAndroid::processEvents() { // Process incoming OS events ALooper_pollAll(0, NULL, NULL, NULL); + + ActivityStates* states = getActivity(NULL); + sf::Lock lock(states->mutex); + + if (m_windowBeingCreated) + { + states->context->createSurface(states->window); + m_windowBeingCreated = false; + } + + if (m_windowBeingDestroyed) + { + states->context->destroySurface(); + m_windowBeingDestroyed = false; + } + + states->updated = true; } @@ -164,21 +185,16 @@ void WindowImplAndroid::setKeyRepeatEnabled(bool enabled) void WindowImplAndroid::forwardEvent(const Event& event) { ActivityStates* states = getActivity(NULL); - Lock lock(states->mutex); if (event.type == Event::GainedFocus) { - states->context->createSurface(states->window); - WindowImplAndroid::singleInstance->m_size.x = ANativeWindow_getWidth(states->window); WindowImplAndroid::singleInstance->m_size.y = ANativeWindow_getHeight(states->window); - - states->updated = true; + WindowImplAndroid::singleInstance->m_windowBeingCreated = true; } else if (event.type == Event::LostFocus) { - states->context->destroySurface(); - states->updated = true; + WindowImplAndroid::singleInstance->m_windowBeingDestroyed = true; } WindowImplAndroid::singleInstance->pushEvent(event); diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index 5c8062e5..1d381aec 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -205,6 +205,8 @@ private: static int getUnicode(AInputEvent* event); Vector2u m_size; + bool m_windowBeingCreated; + bool m_windowBeingDestroyed; }; } // namespace priv