[Android] Improved input implementation

This commit is contained in:
Jonathan De Wachter 2013-10-26 14:08:00 +02:00
parent 4626e95491
commit fbd21962f0
7 changed files with 314 additions and 272 deletions

View File

@ -52,256 +52,6 @@ namespace sf
{ {
namespace priv 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<Mouse::Button>(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<Mouse::Button>(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<Mouse::Button>(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<int>(_event.acceleration.x*1000);
event.mouseWheel.x = static_cast<int>(_event.acceleration.y*1000);
event.mouseWheel.y = static_cast<int>(_event.acceleration.z*1000);
states->pendingEvents.push_back(event);
}
}
ActivityStates* retrieveStates(ANativeActivity* activity) ActivityStates* retrieveStates(ANativeActivity* activity)
{ {
// Hide the ugly cast we find in each callback function // 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); 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; 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) void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
{ {
// Create an activity states (will keep us in the know, about events we care) // 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)); 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) { if (savedState != NULL) {
states->savedState = malloc(savedStateSize); states->savedState = malloc(savedStateSize);
states->savedStateSize = savedStateSize; states->savedStateSize = savedStateSize;

View File

@ -33,9 +33,10 @@
#include <SFML/System/Mutex.hpp> #include <SFML/System/Mutex.hpp>
#include <android/native_activity.h> #include <android/native_activity.h>
#include <android/configuration.h> #include <android/configuration.h>
#include <android/sensor.h>
#include <vector>
#include <EGL/egl.h> #include <EGL/egl.h>
#include <vector>
#include <map>
namespace sf namespace sf
{ {
@ -60,9 +61,12 @@ struct ActivityStates
void* savedState; void* savedState;
size_t savedStateSize; size_t savedStateSize;
sf::Mutex mutex; Mutex mutex;
std::vector<sf::Event> pendingEvents; std::vector<Event> pendingEvents;
int (*processEvent)(int fd, int events, void* data);
std::map<int, Vector2i> touchEvents;
bool mainOver; bool mainOver;

View File

@ -141,7 +141,7 @@ Vector2i InputImpl::getMousePosition()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2i InputImpl::getMousePosition(const Window& relativeTo) 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) bool InputImpl::isTouchDown(unsigned int finger)
{ {
// To implement ALooper_pollAll(0, NULL, NULL, NULL);
return false;
priv::ActivityStates* states = priv::getActivity(NULL);
Lock lock(states->mutex);
return states->touchEvents.find(finger) != states->touchEvents.end();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2i InputImpl::getTouchPosition(unsigned int finger) Vector2i InputImpl::getTouchPosition(unsigned int finger)
{ {
// To implement ALooper_pollAll(0, NULL, NULL, NULL);
return Vector2i();
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) Vector2i InputImpl::getTouchPosition(unsigned int finger, const Window& relativeTo)
{ {
// To implement return getTouchPosition(finger);
return Vector2i();
} }
} // namespace priv } // namespace priv

View File

@ -40,7 +40,7 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
{ {
VideoMode desktop = getDesktopMode(); VideoMode desktop = getDesktopMode();
// Return both protrait and landscape resolutions // Return both portrait and landscape resolutions
std::vector<VideoMode> modes; std::vector<VideoMode> modes;
modes.push_back(desktop); modes.push_back(desktop);
modes.push_back(VideoMode(desktop.height, desktop.width, desktop.bitsPerPixel)); modes.push_back(VideoMode(desktop.height, desktop.width, desktop.bitsPerPixel));

View File

@ -31,6 +31,7 @@
#include <SFML/Window/Event.hpp> #include <SFML/Window/Event.hpp>
#include <SFML/System/Android/Activity.hpp> #include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Lock.hpp> #include <SFML/System/Lock.hpp>
#include <android/looper.h>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -49,6 +50,15 @@ WindowImplAndroid::WindowImplAndroid(WindowHandle handle)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImplAndroid::WindowImplAndroid(VideoMode mode, const std::string& title, unsigned long style, const ContextSettings& settings) 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); ActivityStates* states = getActivity(NULL);
sf::Lock lock(states->mutex); sf::Lock lock(states->mutex);
int ident, events; // Process incoming OS events
void (*addEventToQueue)(ActivityStates*); ALooper_pollAll(0, NULL, NULL, NULL);
while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&addEventToQueue)) >= 0)
{
addEventToQueue(states);
}
while (!states->pendingEvents.empty()) while (!states->pendingEvents.empty())
{ {
@ -111,6 +116,7 @@ void WindowImplAndroid::processEvents()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2i WindowImplAndroid::getPosition() const Vector2i WindowImplAndroid::getPosition() const
{ {
// Not applicable
return Vector2i(0, 0); return Vector2i(0, 0);
} }
@ -118,6 +124,7 @@ Vector2i WindowImplAndroid::getPosition() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplAndroid::setPosition(const Vector2i& position) void WindowImplAndroid::setPosition(const Vector2i& position)
{ {
// Not applicable
} }
@ -137,12 +144,14 @@ void WindowImplAndroid::setSize(const Vector2u& size)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplAndroid::setTitle(const String& title) void WindowImplAndroid::setTitle(const String& title)
{ {
// Not applicable
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplAndroid::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) 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) 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 priv
} // namespace sf } // namespace sf

View File

@ -161,6 +161,28 @@ protected :
private: 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 // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -32,13 +32,13 @@
namespace sf namespace sf
{ {
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::vector<VideoMode> VideoModeImpl::getFullscreenModes() std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
{ {
VideoMode desktop = getDesktopMode(); VideoMode desktop = getDesktopMode();
// Return both protrait and landscape resolutions // Return both portrait and landscape resolutions
std::vector<VideoMode> modes; std::vector<VideoMode> modes;
modes.push_back(desktop); modes.push_back(desktop);
modes.push_back(VideoMode(desktop.height, desktop.width, desktop.bitsPerPixel)); modes.push_back(VideoMode(desktop.height, desktop.width, desktop.bitsPerPixel));