From fbd21962f099c68f9172a1f5b652ac135cf38df3 Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Sat, 26 Oct 2013 14:08:00 +0200 Subject: [PATCH] [Android] Improved input implementation --- src/SFML/Main/MainAndroid.cpp | 263 +----------------- src/SFML/System/Android/Activity.hpp | 12 +- src/SFML/Window/Android/InputImpl.cpp | 21 +- src/SFML/Window/Android/VideoModeImpl.cpp | 2 +- src/SFML/Window/Android/WindowImplAndroid.cpp | 262 ++++++++++++++++- src/SFML/Window/Android/WindowImplAndroid.hpp | 22 ++ src/SFML/Window/iOS/VideoModeImpl.mm | 4 +- 7 files changed, 314 insertions(+), 272 deletions(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index ab050968b..873154dd5 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -52,256 +52,6 @@ namespace sf { namespace priv { -Keyboard::Key mapAndroidKeyToSFMLKey(int32_t key) -{ - switch (key) - { - case AKEYCODE_UNKNOWN : - case AKEYCODE_SOFT_LEFT : - case AKEYCODE_SOFT_RIGHT : - case AKEYCODE_HOME : - case AKEYCODE_BACK : - case AKEYCODE_CALL : - case AKEYCODE_ENDCALL : return Keyboard::Unknown; - case AKEYCODE_0 : return Keyboard::Num0; - case AKEYCODE_1 : return Keyboard::Num1; - case AKEYCODE_2 : return Keyboard::Num2; - case AKEYCODE_3 : return Keyboard::Num3; - case AKEYCODE_4 : return Keyboard::Num4; - case AKEYCODE_5 : return Keyboard::Num5; - case AKEYCODE_6 : return Keyboard::Num6; - case AKEYCODE_7 : return Keyboard::Num7; - case AKEYCODE_8 : return Keyboard::Num8; - case AKEYCODE_9 : return Keyboard::Num9; - case AKEYCODE_STAR : - case AKEYCODE_POUND : - case AKEYCODE_DPAD_UP : - case AKEYCODE_DPAD_DOWN : - case AKEYCODE_DPAD_LEFT : - case AKEYCODE_DPAD_RIGHT : - case AKEYCODE_DPAD_CENTER : - case AKEYCODE_VOLUME_UP : - case AKEYCODE_VOLUME_DOWN : - case AKEYCODE_POWER : - case AKEYCODE_CAMERA : - case AKEYCODE_CLEAR : return Keyboard::Unknown; - case AKEYCODE_A : return Keyboard::A; - case AKEYCODE_B : return Keyboard::B; - case AKEYCODE_C : return Keyboard::C; - case AKEYCODE_D : return Keyboard::D; - case AKEYCODE_E : return Keyboard::E; - case AKEYCODE_F : return Keyboard::F; - case AKEYCODE_G : return Keyboard::G; - case AKEYCODE_H : return Keyboard::H; - case AKEYCODE_I : return Keyboard::I; - case AKEYCODE_J : return Keyboard::J; - case AKEYCODE_K : return Keyboard::K; - case AKEYCODE_L : return Keyboard::L; - case AKEYCODE_M : return Keyboard::M; - case AKEYCODE_N : return Keyboard::N; - case AKEYCODE_O : return Keyboard::O; - case AKEYCODE_P : return Keyboard::P; - case AKEYCODE_Q : return Keyboard::Q; - case AKEYCODE_R : return Keyboard::R; - case AKEYCODE_S : return Keyboard::S; - case AKEYCODE_T : return Keyboard::T; - case AKEYCODE_U : return Keyboard::U; - case AKEYCODE_V : return Keyboard::V; - case AKEYCODE_W : return Keyboard::W; - case AKEYCODE_X : return Keyboard::X; - case AKEYCODE_Y : return Keyboard::Y; - case AKEYCODE_Z : return Keyboard::Z; - case AKEYCODE_COMMA : return Keyboard::Comma; - case AKEYCODE_PERIOD : return Keyboard::Period; - case AKEYCODE_ALT_LEFT : return Keyboard::LAlt; - case AKEYCODE_ALT_RIGHT : return Keyboard::RAlt; - case AKEYCODE_SHIFT_LEFT : return Keyboard::LShift; - case AKEYCODE_SHIFT_RIGHT : return Keyboard::RShift; - case AKEYCODE_TAB : return Keyboard::Tab; - case AKEYCODE_SPACE : return Keyboard::Space; - case AKEYCODE_SYM : - case AKEYCODE_EXPLORER : - case AKEYCODE_ENVELOPE : return Keyboard::Unknown; - case AKEYCODE_ENTER : return Keyboard::Return; - case AKEYCODE_DEL : return Keyboard::Delete; - case AKEYCODE_GRAVE : return Keyboard::Tilde; - case AKEYCODE_MINUS : return Keyboard::Subtract; - case AKEYCODE_EQUALS : return Keyboard::Equal; - case AKEYCODE_LEFT_BRACKET : return Keyboard::LBracket; - case AKEYCODE_RIGHT_BRACKET : return Keyboard::RBracket; - case AKEYCODE_BACKSLASH : return Keyboard::BackSlash; - case AKEYCODE_SEMICOLON : return Keyboard::SemiColon; - case AKEYCODE_APOSTROPHE : return Keyboard::Quote; - case AKEYCODE_SLASH : return Keyboard::Slash; - case AKEYCODE_AT : - case AKEYCODE_NUM : - case AKEYCODE_HEADSETHOOK : - case AKEYCODE_FOCUS : // *Camera* focus - case AKEYCODE_PLUS : - case AKEYCODE_MENU : - case AKEYCODE_NOTIFICATION : - case AKEYCODE_SEARCH : - case AKEYCODE_MEDIA_PLAY_PAUSE : - case AKEYCODE_MEDIA_STOP : - case AKEYCODE_MEDIA_NEXT : - case AKEYCODE_MEDIA_PREVIOUS : - case AKEYCODE_MEDIA_REWIND : - case AKEYCODE_MEDIA_FAST_FORWARD : - case AKEYCODE_MUTE : return Keyboard::Unknown; - case AKEYCODE_PAGE_UP : return Keyboard::PageUp; - case AKEYCODE_PAGE_DOWN : return Keyboard::PageDown; - case AKEYCODE_PICTSYMBOLS : - case AKEYCODE_SWITCH_CHARSET : - case AKEYCODE_BUTTON_A : - case AKEYCODE_BUTTON_B : - case AKEYCODE_BUTTON_C : - case AKEYCODE_BUTTON_X : - case AKEYCODE_BUTTON_Y : - case AKEYCODE_BUTTON_Z : - case AKEYCODE_BUTTON_L1 : - case AKEYCODE_BUTTON_R1 : - case AKEYCODE_BUTTON_L2 : - case AKEYCODE_BUTTON_R2 : - case AKEYCODE_BUTTON_THUMBL : - case AKEYCODE_BUTTON_THUMBR : - case AKEYCODE_BUTTON_START : - case AKEYCODE_BUTTON_SELECT : - case AKEYCODE_BUTTON_MODE : return Keyboard::Unknown; - } -} - - -void processEvent(ActivityStates* states) -{ - // The caller must ensure states can be safely accessed! - - AInputEvent* _event = NULL; - - if (AInputQueue_getEvent(states->inputQueue, &_event) >= 0) - { - if (AInputQueue_preDispatchEvent(states->inputQueue, _event)) - return; - - int32_t handled = 0; - - int32_t type = AInputEvent_getType(_event); - - if (type == AINPUT_EVENT_TYPE_KEY) - { - int32_t action = AKeyEvent_getAction(_event); - - if (action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP) - { - int32_t key = AKeyEvent_getKeyCode(_event); - int32_t metakey = AKeyEvent_getMetaState(_event); - - sf::Event event; - if (action == AKEY_EVENT_ACTION_DOWN) - event.type = Event::KeyPressed; - else - event.type = Event::KeyReleased; - - event.key.code = mapAndroidKeyToSFMLKey(key); - event.key.alt = metakey & AMETA_ALT_ON; - event.key.control = metakey & AMETA_SHIFT_ON; - event.key.shift = false; - - states->pendingEvents.push_back(event); - } - } - else if (type == AINPUT_EVENT_TYPE_MOTION) - { - int32_t action = AMotionEvent_getAction(_event); - - switch (action & AMOTION_EVENT_ACTION_MASK) - { - case AMOTION_EVENT_ACTION_MOVE: - { - int historySize = AMotionEvent_getHistorySize(_event); - int pointerCount = AMotionEvent_getPointerCount(_event); - for (int h = 0; h < historySize; h++) - { - for (int p = 0; p < pointerCount; p++) - { - int id = AMotionEvent_getPointerId(_event, p); - float x = AMotionEvent_getHistoricalX(_event, p, h); - float y = AMotionEvent_getHistoricalY(_event, p, h); - - sf::Event event; - event.type = Event::MouseMoved; - event.mouseButton.button = static_cast(id); - event.mouseButton.x = x; - event.mouseButton.y = y; - states->pendingEvents.push_back(event); - } - } - - break; - } - - case AMOTION_EVENT_ACTION_POINTER_DOWN: - case AMOTION_EVENT_ACTION_DOWN: - { - 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, 0); - float y = AMotionEvent_getY(_event, 0); - - sf::Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = static_cast(id); - event.mouseButton.x = x; - event.mouseButton.y = y; - states->pendingEvents.push_back(event); - - break; - } - - case AMOTION_EVENT_ACTION_POINTER_UP: - case AMOTION_EVENT_ACTION_UP: - case AMOTION_EVENT_ACTION_CANCEL: - { - 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, 0); - float y = AMotionEvent_getY(_event, 0); - - sf::Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = static_cast(id); - event.mouseButton.x = x; - event.mouseButton.y = y; - states->pendingEvents.push_back(event); - - break; - } - } - - } - - handled = 1; - AInputQueue_finishEvent(states->inputQueue, _event, handled); - } -} - -void processSensorEvents(ActivityStates* states) -{ - // The caller must ensure states can be safely accessed! - - ASensorEvent _event; - while (ASensorEventQueue_getEvents(states->sensorEventQueue, &_event, 1) > 0) - { - sf::Event event; - event.type = sf::Event::MouseWheelMoved; - event.mouseWheel.delta = static_cast(_event.acceleration.x*1000); - event.mouseWheel.x = static_cast(_event.acceleration.y*1000); - event.mouseWheel.y = static_cast(_event.acceleration.z*1000); - states->pendingEvents.push_back(event); - } -} - ActivityStates* retrieveStates(ANativeActivity* activity) { // Hide the ugly cast we find in each callback function @@ -503,7 +253,7 @@ static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { sf::Lock lock(states->mutex); - AInputQueue_attachLooper(queue, states->looper, 1, NULL, (void*)&sf::priv::processEvent); + AInputQueue_attachLooper(queue, states->looper, 1, states->processEvent, NULL); states->inputQueue = queue; } } @@ -576,6 +326,12 @@ 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) { // Create an activity states (will keep us in the know, about events we care) @@ -595,6 +351,11 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_ states->display = eglCheck(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) { states->savedState = malloc(savedStateSize); states->savedStateSize = savedStateSize; diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index 5edc1dbd2..b05081d1b 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -33,9 +33,10 @@ #include #include #include -#include -#include #include +#include +#include + namespace sf { @@ -60,9 +61,12 @@ struct ActivityStates void* savedState; size_t savedStateSize; - sf::Mutex mutex; + Mutex mutex; - std::vector pendingEvents; + std::vector pendingEvents; + int (*processEvent)(int fd, int events, void* data); + + std::map touchEvents; bool mainOver; diff --git a/src/SFML/Window/Android/InputImpl.cpp b/src/SFML/Window/Android/InputImpl.cpp index 8e6250683..61dfb0a09 100644 --- a/src/SFML/Window/Android/InputImpl.cpp +++ b/src/SFML/Window/Android/InputImpl.cpp @@ -141,7 +141,7 @@ Vector2i InputImpl::getMousePosition() //////////////////////////////////////////////////////////// Vector2i InputImpl::getMousePosition(const Window& relativeTo) { - return Vector2i(0, 0); + return getMousePosition(); } @@ -162,24 +162,31 @@ void InputImpl::setMousePosition(const Vector2i& position, const Window& relativ //////////////////////////////////////////////////////////// bool InputImpl::isTouchDown(unsigned int finger) { - // To implement - return false; + ALooper_pollAll(0, NULL, NULL, NULL); + + priv::ActivityStates* states = priv::getActivity(NULL); + Lock lock(states->mutex); + + return states->touchEvents.find(finger) != states->touchEvents.end(); } //////////////////////////////////////////////////////////// Vector2i InputImpl::getTouchPosition(unsigned int finger) { - // To implement - return Vector2i(); + ALooper_pollAll(0, NULL, NULL, NULL); + + priv::ActivityStates* states = priv::getActivity(NULL); + Lock lock(states->mutex); + + return states->touchEvents.find(finger)->second; } //////////////////////////////////////////////////////////// Vector2i InputImpl::getTouchPosition(unsigned int finger, const Window& relativeTo) { - // To implement - return Vector2i(); + return getTouchPosition(finger); } } // namespace priv diff --git a/src/SFML/Window/Android/VideoModeImpl.cpp b/src/SFML/Window/Android/VideoModeImpl.cpp index 14f268ae5..3196caeb6 100644 --- a/src/SFML/Window/Android/VideoModeImpl.cpp +++ b/src/SFML/Window/Android/VideoModeImpl.cpp @@ -40,7 +40,7 @@ std::vector VideoModeImpl::getFullscreenModes() { VideoMode desktop = getDesktopMode(); - // Return both protrait and landscape resolutions + // Return both portrait and landscape resolutions std::vector modes; modes.push_back(desktop); modes.push_back(VideoMode(desktop.height, desktop.width, desktop.bitsPerPixel)); diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index cb34b06c9..b0b7f65b1 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -31,6 +31,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////// @@ -49,6 +50,15 @@ WindowImplAndroid::WindowImplAndroid(WindowHandle handle) //////////////////////////////////////////////////////////// WindowImplAndroid::WindowImplAndroid(VideoMode mode, const std::string& title, unsigned long style, const ContextSettings& settings) { + ActivityStates* states = getActivity(NULL); + sf::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 + states->processEvent = processEvent; } @@ -74,13 +84,8 @@ void WindowImplAndroid::processEvents() ActivityStates* states = getActivity(NULL); sf::Lock lock(states->mutex); - int ident, events; - void (*addEventToQueue)(ActivityStates*); - - while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&addEventToQueue)) >= 0) - { - addEventToQueue(states); - } + // Process incoming OS events + ALooper_pollAll(0, NULL, NULL, NULL); while (!states->pendingEvents.empty()) { @@ -111,6 +116,7 @@ void WindowImplAndroid::processEvents() //////////////////////////////////////////////////////////// Vector2i WindowImplAndroid::getPosition() const { + // Not applicable return Vector2i(0, 0); } @@ -118,6 +124,7 @@ Vector2i WindowImplAndroid::getPosition() const //////////////////////////////////////////////////////////// void WindowImplAndroid::setPosition(const Vector2i& position) { + // Not applicable } @@ -137,12 +144,14 @@ void WindowImplAndroid::setSize(const Vector2u& size) //////////////////////////////////////////////////////////// void WindowImplAndroid::setTitle(const String& title) { + // Not applicable } //////////////////////////////////////////////////////////// void WindowImplAndroid::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) { + // Not applicable } @@ -162,5 +171,244 @@ void WindowImplAndroid::setMouseCursorVisible(bool visible) void WindowImplAndroid::setKeyRepeatEnabled(bool enabled) { } + +Keyboard::Key WindowImplAndroid::androidKeyToSF(int32_t key) +{ + switch (key) + { + case AKEYCODE_UNKNOWN : + case AKEYCODE_SOFT_LEFT : + case AKEYCODE_SOFT_RIGHT : + case AKEYCODE_HOME : + case AKEYCODE_BACK : + case AKEYCODE_CALL : + case AKEYCODE_ENDCALL : return Keyboard::Unknown; + case AKEYCODE_0 : return Keyboard::Num0; + case AKEYCODE_1 : return Keyboard::Num1; + case AKEYCODE_2 : return Keyboard::Num2; + case AKEYCODE_3 : return Keyboard::Num3; + case AKEYCODE_4 : return Keyboard::Num4; + case AKEYCODE_5 : return Keyboard::Num5; + case AKEYCODE_6 : return Keyboard::Num6; + case AKEYCODE_7 : return Keyboard::Num7; + case AKEYCODE_8 : return Keyboard::Num8; + case AKEYCODE_9 : return Keyboard::Num9; + case AKEYCODE_STAR : + case AKEYCODE_POUND : + case AKEYCODE_DPAD_UP : + case AKEYCODE_DPAD_DOWN : + case AKEYCODE_DPAD_LEFT : + case AKEYCODE_DPAD_RIGHT : + case AKEYCODE_DPAD_CENTER : + case AKEYCODE_VOLUME_UP : + case AKEYCODE_VOLUME_DOWN : + case AKEYCODE_POWER : + case AKEYCODE_CAMERA : + case AKEYCODE_CLEAR : return Keyboard::Unknown; + case AKEYCODE_A : return Keyboard::A; + case AKEYCODE_B : return Keyboard::B; + case AKEYCODE_C : return Keyboard::C; + case AKEYCODE_D : return Keyboard::D; + case AKEYCODE_E : return Keyboard::E; + case AKEYCODE_F : return Keyboard::F; + case AKEYCODE_G : return Keyboard::G; + case AKEYCODE_H : return Keyboard::H; + case AKEYCODE_I : return Keyboard::I; + case AKEYCODE_J : return Keyboard::J; + case AKEYCODE_K : return Keyboard::K; + case AKEYCODE_L : return Keyboard::L; + case AKEYCODE_M : return Keyboard::M; + case AKEYCODE_N : return Keyboard::N; + case AKEYCODE_O : return Keyboard::O; + case AKEYCODE_P : return Keyboard::P; + case AKEYCODE_Q : return Keyboard::Q; + case AKEYCODE_R : return Keyboard::R; + case AKEYCODE_S : return Keyboard::S; + case AKEYCODE_T : return Keyboard::T; + case AKEYCODE_U : return Keyboard::U; + case AKEYCODE_V : return Keyboard::V; + case AKEYCODE_W : return Keyboard::W; + case AKEYCODE_X : return Keyboard::X; + case AKEYCODE_Y : return Keyboard::Y; + case AKEYCODE_Z : return Keyboard::Z; + case AKEYCODE_COMMA : return Keyboard::Comma; + case AKEYCODE_PERIOD : return Keyboard::Period; + case AKEYCODE_ALT_LEFT : return Keyboard::LAlt; + case AKEYCODE_ALT_RIGHT : return Keyboard::RAlt; + case AKEYCODE_SHIFT_LEFT : return Keyboard::LShift; + case AKEYCODE_SHIFT_RIGHT : return Keyboard::RShift; + case AKEYCODE_TAB : return Keyboard::Tab; + case AKEYCODE_SPACE : return Keyboard::Space; + case AKEYCODE_SYM : + case AKEYCODE_EXPLORER : + case AKEYCODE_ENVELOPE : return Keyboard::Unknown; + case AKEYCODE_ENTER : return Keyboard::Return; + case AKEYCODE_DEL : return Keyboard::Delete; + case AKEYCODE_GRAVE : return Keyboard::Tilde; + case AKEYCODE_MINUS : return Keyboard::Subtract; + case AKEYCODE_EQUALS : return Keyboard::Equal; + case AKEYCODE_LEFT_BRACKET : return Keyboard::LBracket; + case AKEYCODE_RIGHT_BRACKET : return Keyboard::RBracket; + case AKEYCODE_BACKSLASH : return Keyboard::BackSlash; + case AKEYCODE_SEMICOLON : return Keyboard::SemiColon; + case AKEYCODE_APOSTROPHE : return Keyboard::Quote; + case AKEYCODE_SLASH : return Keyboard::Slash; + case AKEYCODE_AT : + case AKEYCODE_NUM : + case AKEYCODE_HEADSETHOOK : + case AKEYCODE_FOCUS : // *Camera* focus + case AKEYCODE_PLUS : + case AKEYCODE_MENU : + case AKEYCODE_NOTIFICATION : + case AKEYCODE_SEARCH : + case AKEYCODE_MEDIA_PLAY_PAUSE : + case AKEYCODE_MEDIA_STOP : + case AKEYCODE_MEDIA_NEXT : + case AKEYCODE_MEDIA_PREVIOUS : + case AKEYCODE_MEDIA_REWIND : + case AKEYCODE_MEDIA_FAST_FORWARD : + case AKEYCODE_MUTE : return Keyboard::Unknown; + case AKEYCODE_PAGE_UP : return Keyboard::PageUp; + case AKEYCODE_PAGE_DOWN : return Keyboard::PageDown; + case AKEYCODE_PICTSYMBOLS : + case AKEYCODE_SWITCH_CHARSET : + case AKEYCODE_BUTTON_A : + case AKEYCODE_BUTTON_B : + case AKEYCODE_BUTTON_C : + case AKEYCODE_BUTTON_X : + case AKEYCODE_BUTTON_Y : + case AKEYCODE_BUTTON_Z : + case AKEYCODE_BUTTON_L1 : + case AKEYCODE_BUTTON_R1 : + case AKEYCODE_BUTTON_L2 : + case AKEYCODE_BUTTON_R2 : + case AKEYCODE_BUTTON_THUMBL : + case AKEYCODE_BUTTON_THUMBR : + case AKEYCODE_BUTTON_START : + case AKEYCODE_BUTTON_SELECT : + case AKEYCODE_BUTTON_MODE : return Keyboard::Unknown; + } +} + +int WindowImplAndroid::processEvent(int fd, int events, void* data) +{ + ActivityStates* states = getActivity(NULL); + Lock lock(states->mutex); + + AInputEvent* _event = NULL; + + if (AInputQueue_getEvent(states->inputQueue, &_event) >= 0) + { + if (AInputQueue_preDispatchEvent(states->inputQueue, _event)) + return 1; + + int32_t handled = 0; + + int32_t type = AInputEvent_getType(_event); + + if (type == AINPUT_EVENT_TYPE_KEY) + { + int32_t action = AKeyEvent_getAction(_event); + + if (action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP) + { + int32_t key = AKeyEvent_getKeyCode(_event); + int32_t metakey = AKeyEvent_getMetaState(_event); + + sf::Event event; + event.type = (action == AKEY_EVENT_ACTION_DOWN) ? Event::KeyPressed : Event::KeyReleased; + event.key.code = androidKeyToSF(key); + event.key.alt = metakey & AMETA_ALT_ON; + event.key.control = false; + event.key.shift = metakey & AMETA_SHIFT_ON; + + states->pendingEvents.push_back(event); + } + } + else if (type == AINPUT_EVENT_TYPE_MOTION) + { + int32_t action = AMotionEvent_getAction(_event); + + switch (action & AMOTION_EVENT_ACTION_MASK) + { + case AMOTION_EVENT_ACTION_MOVE: + { + int pointerCount = AMotionEvent_getPointerCount(_event); + + Event event; + event.type = Event::TouchMoved; + + for (int p = 0; p < pointerCount; p++) + { + int id = AMotionEvent_getPointerId(_event, p); + event.touch.finger = id; + + float x = AMotionEvent_getX(_event, p); + float y = AMotionEvent_getY(_event, p); + + event.touch.x = x; + event.touch.y = y; + states->pendingEvents.push_back(event); + + states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); + } + + break; + } + + case AMOTION_EVENT_ACTION_POINTER_DOWN: + case AMOTION_EVENT_ACTION_DOWN: + { + 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, 0); + float y = AMotionEvent_getY(_event, 0); + + Event event; + event.type = Event::TouchBegan; + event.touch.finger = id; + event.touch.x = x; + event.touch.y = y; + states->pendingEvents.push_back(event); + + + states->touchEvents[id] = Vector2i(x, y); + + break; + } + + case AMOTION_EVENT_ACTION_POINTER_UP: + case AMOTION_EVENT_ACTION_UP: + case AMOTION_EVENT_ACTION_CANCEL: + { + 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, 0); + float y = AMotionEvent_getY(_event, 0); + + Event event; + event.type = Event::TouchEnded; + event.touch.finger = id; + event.touch.x = x; + event.touch.y = y; + states->pendingEvents.push_back(event); + + + states->touchEvents.erase(id); + + break; + } + } + + } + + handled = 1; + AInputQueue_finishEvent(states->inputQueue, _event, handled); + } + + return 1; +} } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index b28ca632e..91e8c44f2 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -161,6 +161,28 @@ protected : private: + //////////////////////////////////////////////////////////// + /// \brief Convert a Android key to SFML key code + /// + /// \param symbol Android key to convert + /// + /// \return Corrsponding SFML key code + /// + //////////////////////////////////////////////////////////// + static Keyboard::Key androidKeyToSF(int32_t key); + + //////////////////////////////////////////////////////////// + /// \brief Process messages from the looper associated with the main thread + /// + /// \param fd File descriptor + /// \param events Bitmask of the poll events that were triggered + /// \param data Data pointer supplied + /// + /// \return Whether it should continue (1) or unregister the callback (0) + /// + //////////////////////////////////////////////////////////// + static int processEvent(int fd, int events, void* data); + //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// diff --git a/src/SFML/Window/iOS/VideoModeImpl.mm b/src/SFML/Window/iOS/VideoModeImpl.mm index 1e91b4c9a..96adb7b01 100644 --- a/src/SFML/Window/iOS/VideoModeImpl.mm +++ b/src/SFML/Window/iOS/VideoModeImpl.mm @@ -32,13 +32,13 @@ namespace sf { namespace priv -{ +{ //////////////////////////////////////////////////////////// std::vector VideoModeImpl::getFullscreenModes() { VideoMode desktop = getDesktopMode(); - // Return both protrait and landscape resolutions + // Return both portrait and landscape resolutions std::vector modes; modes.push_back(desktop); modes.push_back(VideoMode(desktop.height, desktop.width, desktop.bitsPerPixel));