Merge pull request #748 from wesnoth/staging-event-handlers

Staging area for event handlers
This commit is contained in:
Andreas 2016-08-14 08:56:59 +12:00 committed by GitHub
commit 9469b9b6c1
4 changed files with 53 additions and 50 deletions

View file

@ -34,6 +34,7 @@
#include <utility>
#include <vector>
#include <algorithm>
#include <iterator>
#include <boost/thread.hpp>
#define ERR_GEN LOG_STREAM(err, lg::general)
@ -43,7 +44,10 @@ namespace events
void context::add_handler(sdl_handler* ptr)
{
handlers.push_back(ptr);
/* Add new handlers to the staging list initially.
This ensures that if an event handler adds more handlers, the new handlers
won't be called for the event that caused them to be added. */
staging_handlers.push_back(ptr);
}
bool context::remove_handler(sdl_handler* ptr)
@ -68,7 +72,18 @@ bool context::remove_handler(sdl_handler* ptr)
if(i == handlers.end()) {
--depth;
return false;
// The handler may be in the staging area. Search it from there.
auto j = std::find(staging_handlers.begin(), staging_handlers.end(), ptr);
if (j != staging_handlers.end())
{
staging_handlers.erase(j);
return true;
}
else
{
return false;
}
}
if(i == focused_handler) {
@ -131,6 +146,12 @@ void context::set_focus(const sdl_handler* ptr)
}
}
void context::add_staging_handlers()
{
std::copy(staging_handlers.begin(), staging_handlers.end(), std::back_inserter(handlers));
staging_handlers.clear();
}
context::~context()
{
for (sdl_handler* h : handlers)
@ -445,6 +466,11 @@ void pump()
ev_end = events.end();
for(ev_it = events.begin(); ev_it != ev_end; ++ev_it){
for (context& c : event_contexts)
{
c.add_staging_handlers();
}
SDL_Event &event = *ev_it;
switch(event.type) {

View file

@ -41,7 +41,8 @@ class context
public:
context() :
handlers(),
focused_handler(handlers.end())
focused_handler(handlers.end()),
staging_handlers()
{
}
@ -53,9 +54,11 @@ public:
bool remove_handler(sdl_handler* ptr);
void cycle_focus();
void set_focus(const sdl_handler* ptr);
void add_staging_handlers();
handler_list handlers;
handler_list::iterator focused_handler;
std::vector<sdl_handler*> staging_handlers;
};
//any classes that derive from this class will automatically

View file

@ -30,20 +30,21 @@ static lg::log_domain log_display("display");
namespace gui {
textbox::textbox(CVideo &video, int width, const std::string& text, bool editable, size_t max_size, int font_size, double alpha, double alpha_focus, const bool auto_join) :
scrollarea(video, auto_join), max_size_(max_size), font_size_(font_size), text_(unicode_cast<ucs4::string>(text)),
cursor_(text_.size()), selstart_(-1), selend_(-1),
grabmouse_(false), text_pos_(0), editable_(editable),
show_cursor_(true), show_cursor_at_(0), text_image_(nullptr),
wrap_(false), line_height_(0), yscroll_(0), alpha_(alpha),
alpha_focus_(alpha_focus),
edit_target_(nullptr),
initially_pressed_keys_()
textbox::textbox(CVideo &video, int width, const std::string& text, bool editable, size_t max_size, int font_size, double alpha, double alpha_focus, const bool auto_join)
: scrollarea(video, auto_join), max_size_(max_size), font_size_(font_size), text_(unicode_cast<ucs4::string>(text)),
cursor_(text_.size()), selstart_(-1), selend_(-1),
grabmouse_(false), text_pos_(0), editable_(editable),
show_cursor_(true), show_cursor_at_(0), text_image_(nullptr),
wrap_(false), line_height_(0), yscroll_(0), alpha_(alpha),
alpha_focus_(alpha_focus),
edit_target_(nullptr)
,listening_(false)
{
// static const SDL_Rect area = d.screen_area();
// const int height = font::draw_text(nullptr,area,font_size,font::NORMAL_COLOR,"ABCD",0,0).h;
set_measurements(width, font::get_max_height(font_size_));
set_scroll_rate(font::get_max_height(font_size_) / 2);
update_text_cache(true);
determine_initially_pressed_keys();
}
textbox::~textbox()
@ -476,6 +477,8 @@ bool textbox::handle_key_down(const SDL_Event &event)
const int c = key.sym;
const int old_cursor = cursor_;
listening_ = true;
if(editable_) {
if(c == SDLK_LEFT && cursor_ > 0)
--cursor_;
@ -595,12 +598,6 @@ bool textbox::handle_key_down(const SDL_Event &event)
return changed;
}
bool textbox::handle_key_up(const SDL_Event& event)
{
initially_pressed_keys_.erase(static_cast<uint16_t>(event.key.keysym.scancode));
return false;
}
void textbox::handle_event(const SDL_Event& event, bool was_forwarded)
{
if(!enabled())
@ -682,14 +679,11 @@ void textbox::handle_event(const SDL_Event& event, bool was_forwarded)
const int old_cursor = cursor_;
if (event.type == SDL_TEXTINPUT && is_listening()) {
if (event.type == SDL_TEXTINPUT && listening_) {
changed = handle_text_input(event);
}
else if (event.type == SDL_KEYDOWN) {
changed = handle_key_down(event);
}
else if (event.type == SDL_KEYUP) {
changed = handle_key_up(event);
} else
if (event.type == SDL_KEYDOWN) {
changed = handle_key_down(event);
}
else {
if(event.type != SDL_KEYDOWN || (!was_forwarded && focus(&event) != true)) {
@ -727,17 +721,4 @@ void textbox::set_edit_target(textbox* target)
edit_target_ = target;
}
void textbox::determine_initially_pressed_keys()
{
int num_keys;
const uint8_t* keys = SDL_GetKeyboardState(&num_keys);
for (uint16_t i = 0u; i < static_cast<uint16_t>(num_keys); ++i)
{
if (keys[i] == 1u)
{
initially_pressed_keys_.insert(i);
}
}
}
} //end namespace gui

View file

@ -17,8 +17,6 @@
#include "serialization/unicode.hpp"
#include "font.hpp"
#include <cstdint>
#include <set>
#include "scrollarea.hpp"
@ -94,15 +92,11 @@ private:
textbox* edit_target_;
/* This set contains all the keys which were pressed when the textbox was created.
* This is needed to block the textbox from receiving text input from a hotkey
* that was used to spawn the textbox in the first place.
/* This boolean is used to filter out any TextInput events that are received without
* the corresponding KeyPress events. This is needed to avoid a bug when creating a
* textbox using a hotkey.
* */
std::set<uint16_t> initially_pressed_keys_;
bool is_listening() const { return initially_pressed_keys_.empty(); }
void determine_initially_pressed_keys();
bool listening_;
void handle_event(const SDL_Event& event, bool was_forwarded);
@ -123,7 +117,6 @@ private:
bool show_scrollbar() const;
bool handle_text_input(const SDL_Event& event);
bool handle_key_down(const SDL_Event &event);
bool handle_key_up(const SDL_Event &event);
};
}