3 kinds of touch event compiled: up/down (combined with mouse), swipe and multi-finger gesture.

This commit is contained in:
Victor Sergienko 2017-03-14 13:47:38 -07:00 committed by Jyrki Vesterinen
parent 19c2c9364f
commit ea2e16d251
5 changed files with 179 additions and 28 deletions

View file

@ -31,6 +31,8 @@ dispatcher::dispatcher()
, signal_queue_()
, signal_mouse_queue_()
, signal_keyboard_queue_()
, signal_touch_motion_queue_()
, signal_touch_gesture_queue_()
, signal_notification_queue_()
, signal_message_queue_()
, connected_(false)
@ -64,6 +66,12 @@ bool dispatcher::has_event(const ui_event event, const event_queue_type event_ty
<< find<set_event_mouse>(event, dispatcher_implementation
::has_handler(event_type, *this))
<< " keyboard "
<< find<set_event_touch_motion>(event, dispatcher_implementation
::has_handler(event_type, *this))
<< " touch_motion "
<< find<set_event_touch_gesture>(event, dispatcher_implementation
::has_handler(event_type, *this))
<< " touch_gesture "
<< find<set_event_keyboard>(event, dispatcher_implementation
::has_handler(event_type, *this))
<< " notification "
@ -83,7 +91,9 @@ bool dispatcher::has_event(const ui_event event, const event_queue_type event_ty
event, dispatcher_implementation::has_handler(event_type, *this))
|| find<set_event_text_input>(
event, dispatcher_implementation::has_handler(event_type, *this))
|| find<set_event_touch>(
|| find<set_event_touch_motion>(
event, dispatcher_implementation::has_handler(event_type, *this))
|| find<set_event_touch_gesture>(
event, dispatcher_implementation::has_handler(event_type, *this))
|| find<set_event_notification>(
event, dispatcher_implementation::has_handler(event_type, *this))
@ -154,6 +164,18 @@ bool dispatcher::fire(const ui_event event,
return fire_event<signal_keyboard_function>(event, this, &target, key, modifier, unicode);
}
bool dispatcher::fire(const ui_event event, widget& target, const point& pos, const point& distance)
{
assert(find<set_event_touch_motion>(event, event_in_set()));
return fire_event<signal_touch_motion_function>(event, this, &target, pos, distance);
}
bool dispatcher::fire(const ui_event event, widget& target, const point& center, float dTheta, float dDist, Uint8 numFingers)
{
assert(find<set_event_touch_gesture>(event, event_in_set()));
return fire_event<signal_touch_gesture_function>(event, this, &target, center, dTheta, dDist, numFingers);
}
bool dispatcher::fire(const ui_event event, widget& target, const SDL_Event& sdlevent)
{
assert(find<set_event_raw_event>(event, event_in_set()));
@ -166,12 +188,6 @@ bool dispatcher::fire(const ui_event event, widget& target, const std::string& t
return fire_event<signal_text_input_function>(event, this, &target, text, start, len);
}
bool dispatcher::fire(const ui_event event, widget& target, const point& pos, const point& distance)
{
assert(find<set_event_touch>(event, event_in_set()));
return fire_event<signal_touch_function>(event, this, &target, pos, distance);
}
bool dispatcher::fire(const ui_event event, widget& target, void*)
{
assert(find<set_event_notification>(event, event_in_set()));

View file

@ -80,14 +80,28 @@ typedef std::function<void(widget& dispatcher,
/**
* Callback function signature.
*
* This function is used for the callbacks in set_event_touch.
* This function is used for the callbacks in set_event_touch_motion.
*/
typedef std::function<void(widget& dispatcher,
const ui_event event,
bool& handled,
bool& halt,
const point& pos,
const point& distance)> signal_touch_function;
const point& distance)> signal_touch_motion_function;
/**
* Callback function signature.
*
* This function is used for the callbacks in set_event_touch_gesture.
*/
typedef std::function<void(dispatcher& dispatcher,
const ui_event event,
bool& handled,
bool& halt,
const point& center,
float dTheta,
float dDist,
Uint8 numFingers)> signal_touch_gesture_function;
/**
* Callback function signature.
@ -226,7 +240,7 @@ public:
const std::string& unicode);
/**
* Fires an event which takes touch parameters.
* Fires an event which takes touch-motion parameters.
*
* @param event The event to fire.
* @param target The widget that should receive the event.
@ -237,6 +251,23 @@ public:
widget& target,
const point& pos,
const point& distance);
/**
* Fires an event which takes touch-gesture parameters.
*
* @param event The event to fire.
* @param target The widget that should receive the event.
* @param pos The location touched.
* @param distance The distance moved.
*/
bool fire(const ui_event event,
widget& target,
const point& center,
float dTheta,
float dDist,
Uint8 numFingers);
/**
* Fires an event which takes notification parameters.
@ -448,18 +479,18 @@ public:
}
/**
* Connect a signal for callback in set_event_touch.
* Connect a signal for callback in set_event_touch_motion.
*
* @tparam E The event the callback needs to react to.
* @param signal The callback function.
* @param position The position to place the callback.
*/
template <ui_event E>
std::enable_if_t<has_key<set_event_touch, E>::value>
connect_signal(const signal_touch_function& signal,
std::enable_if_t<has_key<set_event_touch_motion, E>::value>
connect_signal(const signal_touch_motion_function& signal,
const queue_position position = back_child)
{
signal_touch_queue_.connect_signal(E, position, signal);
signal_touch_motion_queue_.connect_signal(E, position, signal);
}
/**
@ -473,11 +504,44 @@ public:
* was added in front or back.)
*/
template <ui_event E>
std::enable_if_t<has_key<set_event_touch, E>::value>
disconnect_signal(const signal_touch_function& signal,
std::enable_if_t<has_key<set_event_touch_motion, E>::value>
disconnect_signal(const signal_touch_motion_function& signal,
const queue_position position = back_child)
{
signal_touch_queue_.disconnect_signal(E, position, signal);
signal_touch_motion_queue_.disconnect_signal(E, position, signal);
}
/**
* Connect a signal for callback in set_event_touch_gesture.
*
* @tparam E The event the callback needs to react to.
* @param signal The callback function.
* @param position The position to place the callback.
*/
template <ui_event E>
std::enable_if_t<has_key<set_event_touch_gesture, E>::value>
connect_signal(const signal_touch_gesture_function& signal,
const queue_position position = back_child)
{
signal_touch_gesture_queue_.connect_signal(E, position, signal);
}
/**
* Disconnect a signal for callback in set_event_touch.
*
* @tparam E The event the callback was used for.
* @param signal The callback function.
* @param position The place where the function was added.
* Needed remove the event from the right
* place. (The function doesn't care whether
* was added in front or back.)
*/
template <ui_event E>
std::enable_if_t<has_key<set_event_touch_gesture, E>::value>
disconnect_signal(const signal_touch_gesture_function& signal,
const queue_position position = back_child)
{
signal_touch_gesture_queue_.disconnect_signal(E, position, signal);
}
/**
@ -824,7 +888,10 @@ private:
signal_queue<signal_keyboard_function> signal_keyboard_queue_;
/** Signal queue for callbacks in set_event_touch. */
signal_queue<signal_touch_function> signal_touch_queue_;
signal_queue<signal_touch_motion_function> signal_touch_motion_queue_;
/** Signal queue for callbacks in set_event_touch. */
signal_queue<signal_touch_gesture_function> signal_touch_gesture_queue_;
/** Signal queue for callbacks in set_event_notification. */
signal_queue<signal_notification_function> signal_notification_queue_;

View file

@ -105,7 +105,8 @@ struct dispatcher_implementation
IMPLEMENT_EVENT_SIGNAL_WRAPPER(mouse)
IMPLEMENT_EVENT_SIGNAL_WRAPPER(keyboard)
IMPLEMENT_EVENT_SIGNAL_WRAPPER(touch)
IMPLEMENT_EVENT_SIGNAL_WRAPPER(touch_motion)
IMPLEMENT_EVENT_SIGNAL_WRAPPER(touch_gesture)
IMPLEMENT_EVENT_SIGNAL_WRAPPER(notification)
IMPLEMENT_EVENT_SIGNAL_WRAPPER(message)
IMPLEMENT_EVENT_SIGNAL_WRAPPER(raw_event)

View file

@ -224,12 +224,35 @@ private:
dispatcher* keyboard_dispatcher();
/**
* Fires a generic touch event.
* Fires a touch-moved event.
*
* @param position The position touched.
* @param distance The distance moved.
*/
void touch_motion(const point& position, const point& distance);
/**
* Fires a touch "finger down" event.
*
* @param position The position touched.
*/
void touch_down(const point& position);
/**
* Fires a touch "finger up" event.
*
* @param position The position touched.
*/
void touch_up(const point& position);
/**
* Fires a touch gesture event.
* @param center the center of gesture
* @param dTheta the amount that the fingers rotated during this motion
* @param dDist the amount that the fingers pinched during this motion
* @param numFingers the number of fingers used in the gesture
*/
void touch_multi_gesture(const point& center, float dTheta, float dDist, Uint8 numFingers);
/**
* Handles a hat motion event.
@ -445,6 +468,19 @@ void sdl_event_handler::handle_event(const SDL_Event& event)
touch_motion(point(event.tfinger.x, event.tfinger.y), point(event.tfinger.dx, event.tfinger.dy));
break;
case SDL_FINGERUP:
touch_up(point(event.tfinger.x, event.tfinger.y));
break;
case SDL_FINGERDOWN:
touch_down(point(event.tfinger.x, event.tfinger.y));
break;
case SDL_MULTIGESTURE:
touch_multi_gesture(point(event.mgesture.x, event.mgesture.y),
event.mgesture.dTheta, event.mgesture.dDist, event.mgesture.numFingers);
break;
#if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32)
case SDL_SYSWMEVENT:
/* DO NOTHING */
@ -454,8 +490,6 @@ void sdl_event_handler::handle_event(const SDL_Event& event)
// Silently ignored events.
case SDL_KEYUP:
case DOUBLE_CLICK_EVENT:
case SDL_FINGERUP:
case SDL_FINGERDOWN:
break;
default:
@ -677,6 +711,27 @@ void sdl_event_handler::touch_motion(const point& position, const point& distanc
}
}
void sdl_event_handler::touch_up(const point& position)
{
for(auto& dispatcher : boost::adaptors::reverse(dispatchers_)) {
dispatcher->fire(SDL_TOUCH_UP, dynamic_cast<widget&>(*dispatcher), position);
}
}
void sdl_event_handler::touch_down(const point& position)
{
for(auto& dispatcher : boost::adaptors::reverse(dispatchers_)) {
dispatcher->fire(SDL_TOUCH_DOWN, dynamic_cast<widget&>(*dispatcher), position);
}
}
void sdl_event_handler::touch_multi_gesture(const point& center, float dTheta, float dDist, Uint8 numFingers)
{
for(auto& dispatcher : boost::adaptors::reverse(dispatchers_)) {
dispatcher->fire(SDL_TOUCH_MULTI_GESTURE, dynamic_cast<widget&>(*dispatcher), center, dTheta, dDist, numFingers);
}
}
void sdl_event_handler::hat_motion(const SDL_Event& event)
{
const hotkey::hotkey_ptr& hk = hotkey::get_hotkey(event);
@ -1009,6 +1064,9 @@ std::ostream& operator<<(std::ostream& stream, const ui_event event)
case SDL_TOUCH_DOWN:
stream << "SDL touch down";
break;
case SDL_TOUCH_MULTI_GESTURE:
stream << "SDL multi-touch gesture";
break;
case SDL_RAW_EVENT:
stream << "SDL raw event";
break;

View file

@ -116,6 +116,7 @@ enum ui_event {
SDL_TOUCH_MOTION,
SDL_TOUCH_UP,
SDL_TOUCH_DOWN,
SDL_TOUCH_MULTI_GESTURE,
SDL_RAW_EVENT /**< Raw SDL event. */
};
@ -168,7 +169,9 @@ typedef boost::mpl::set<boost::mpl::int_<SDL_VIDEO_RESIZE>,
boost::mpl::int_<SDL_WHEEL_UP>,
boost::mpl::int_<SDL_WHEEL_DOWN>,
boost::mpl::int_<SDL_WHEEL_LEFT>,
boost::mpl::int_<SDL_WHEEL_RIGHT>> set_event_mouse;
boost::mpl::int_<SDL_WHEEL_RIGHT>,
boost::mpl::int_<SDL_TOUCH_UP>,
boost::mpl::int_<SDL_TOUCH_DOWN>> set_event_mouse;
/**
* Helper for catching use error of dispatcher::connect_signal.
@ -181,12 +184,18 @@ typedef boost::mpl::set<boost::mpl::int_<SDL_KEY_DOWN>> set_event_keyboard;
/**
* Helper for catching use error of dispatcher::connect_signal.
*
* This version is for callbacks of touch events.
* This version is for callbacks of touch motion events.
*/
typedef boost::mpl::set<boost::mpl::int_<SDL_TOUCH_MOTION>,
boost::mpl::int_<SDL_TOUCH_UP>,
boost::mpl::int_<SDL_TOUCH_DOWN>>
set_event_touch;
typedef boost::mpl::set<boost::mpl::int_<SDL_TOUCH_MOTION>>
set_event_touch_motion;
/**
* Helper for catching use error of dispatcher::connect_signal.
*
* This version is for callbacks of touch gestures events.
*/
typedef boost::mpl::set<boost::mpl::int_<SDL_TOUCH_MULTI_GESTURE>>
set_event_touch_gesture;
/**
* Helper for catching use error of dispatcher::connect_signal.