mirror of
https://github.com/SFML/SFML.git
synced 2024-11-29 06:41:05 +08:00
[Android] Improved input implementation
This commit is contained in:
parent
4626e95491
commit
fbd21962f0
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -38,7 +38,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));
|
||||||
|
Loading…
Reference in New Issue
Block a user