Merge pull request #748 from wesnoth/staging-event-handlers
Staging area for event handlers
This commit is contained in:
commit
9469b9b6c1
4 changed files with 53 additions and 50 deletions
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue