Fix a stray ; character appearing in the command console
The GUI1 textbox widget had a mechanism to reject input until it has
received an SDL_KEYDOWN event, but it didn't do any good. I suspect this
regressed in commit 61ccf2fc
, which changed the type of the event handler
container from std::vector to std::list. Apparently, starting from that
commit, an event (say, an SDL_KEYDOWN event) will also be delivered to
any event listeners which are registered by existing event handlers.
In other words:
1. the player presses ;
2. SDL generates an SDL_KEYDOWN event
3. a handler for that event creates the command console
4. the command console registers a handler for SDL events
5. the original keypress event is delivered to the command console
6. the console starts listening for input as a result of that event
7. SDL generates an SDL_TEXTINPUT event, still for the same keypress
8. the console inserts the ; character
I made the textbox loop through all the keys in construction, and store a
set of all pressed keys. The box will ignore all input until all the keys
which were down at the time it was created have been released. The fix
stops the stray ; character from appearing.
This commit is contained in:
parent
087a2822d1
commit
3d8c29bc29
4 changed files with 50 additions and 21 deletions
|
@ -51,6 +51,7 @@ Version 1.13.5+dev:
|
|||
high HP, drain, slow, berserk, etc.) it's significantly faster than the default
|
||||
damage calculation method.
|
||||
* Miscellaneous and bug fixes:
|
||||
* Fixed a stray ; character appearing pre-entered in the command console.
|
||||
* Fixed bug in wesnothd that was causing server crashes if game with
|
||||
multiple network and local players was ran.
|
||||
* Added a tab to run the wmlxgettext tool to GUI.pyw
|
||||
|
|
|
@ -15,6 +15,8 @@ Version 1.13.5+dev:
|
|||
probabilities. This method is inexact, but in very complex battles (extremely
|
||||
high HP, drain, slow, berserk, etc.) it's significantly faster than the default
|
||||
damage calculation method.
|
||||
* Miscellaneous and bug fixes:
|
||||
* Fixed a stray ; character appearing pre-entered in the command console.
|
||||
|
||||
Version 1.13.5:
|
||||
* Campaigns:
|
||||
|
|
|
@ -30,21 +30,20 @@ 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)
|
||||
,listening_(false)
|
||||
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_()
|
||||
{
|
||||
// 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()
|
||||
|
@ -477,8 +476,6 @@ 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_;
|
||||
|
@ -598,6 +595,12 @@ 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())
|
||||
|
@ -679,11 +682,14 @@ void textbox::handle_event(const SDL_Event& event, bool was_forwarded)
|
|||
|
||||
const int old_cursor = cursor_;
|
||||
|
||||
if (event.type == SDL_TEXTINPUT && listening_) {
|
||||
if (event.type == SDL_TEXTINPUT && is_listening()) {
|
||||
changed = handle_text_input(event);
|
||||
} else
|
||||
if (event.type == SDL_KEYDOWN) {
|
||||
changed = handle_key_down(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 || (!was_forwarded && focus(&event) != true)) {
|
||||
|
@ -721,4 +727,17 @@ 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,6 +17,8 @@
|
|||
|
||||
#include "serialization/unicode.hpp"
|
||||
#include "font.hpp"
|
||||
#include <cstdint>
|
||||
#include <set>
|
||||
|
||||
#include "scrollarea.hpp"
|
||||
|
||||
|
@ -92,11 +94,15 @@ private:
|
|||
|
||||
textbox* edit_target_;
|
||||
|
||||
/* 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.
|
||||
/* 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.
|
||||
* */
|
||||
bool listening_;
|
||||
std::set<uint16_t> initially_pressed_keys_;
|
||||
|
||||
bool is_listening() const { return initially_pressed_keys_.empty(); }
|
||||
|
||||
void determine_initially_pressed_keys();
|
||||
|
||||
void handle_event(const SDL_Event& event, bool was_forwarded);
|
||||
|
||||
|
@ -117,6 +123,7 @@ 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