Add the keyboard event chaining.

The mp selection dialog is the only dialog which can benefit from it
so the only dialog which chains the keyboard events. (The window
itself is always chained eventhough there's no hotkey support yet.)

When the listbox has the focus and ends at the top item the next up
arrow is send to the textbox which selects from the history there. Not
sure whether this is great behaviour, but it can be changed by letting
the listbox always handle the up arrow.
This commit is contained in:
Mark de Wever 2008-06-23 19:34:16 +00:00
parent 1e79743e6f
commit 8268e382de
4 changed files with 54 additions and 4 deletions

View file

@ -65,6 +65,9 @@ void tmp_method_selection::pre_show(CVideo& /*video*/, twindow& window)
tlistbox* list = dynamic_cast<tlistbox*>(window.find_widget("method_list", false));
VALIDATE(list, missing_widget("method_list"));
window.add_to_keyboard_chain(list);
window.add_to_keyboard_chain(user_widget);
window.recalculate_size();
}

View file

@ -108,7 +108,8 @@ tevent_handler::tevent_handler() :
help_popup_(0),
mouse_focus_(0),
mouse_captured_(false),
keyboard_focus_(0)
keyboard_focus_(0),
keyboard_focus_chain_()
{
if(SDL_WasInit(SDL_INIT_TIMER) == 0) {
if(SDL_InitSubSystem(SDL_INIT_TIMER) == -1) {
@ -240,6 +241,25 @@ tpoint tevent_handler::get_mouse() const
return get_window().client_position(tpoint(mouse_x_, mouse_y_));
}
void tevent_handler::add_to_keyboard_chain(twidget* widget)
{
assert(
std::find(keyboard_focus_chain_.begin(), keyboard_focus_chain_.end(), widget)
== keyboard_focus_chain_.end());
keyboard_focus_chain_.push_back(widget);
}
void tevent_handler::remove_from_keyboard_chain(twidget* widget)
{
std::vector<twidget*>::iterator itor = std::find(
keyboard_focus_chain_.begin(), keyboard_focus_chain_.end(), widget);
if(itor != keyboard_focus_chain_.end()) {
keyboard_focus_chain_.erase(itor);
}
}
void tevent_handler::show_tooltip(const t_string& tooltip, const unsigned timeout)
{
DBG_G_E << "Event: show tooltip.\n";
@ -510,11 +530,18 @@ void tevent_handler::key_down(const SDL_Event& event)
bool handled = false;
if(keyboard_focus_) {
keyboard_focus_->key_press(*this, handled, event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
keyboard_focus_->key_press(*this, handled,
event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
}
if(!handled) {
get_window().key_press(*this, handled, event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
std::vector<twidget*>::reverse_iterator ritor = keyboard_focus_chain_.rbegin();
for(; !handled && ritor != keyboard_focus_chain_.rend(); ++ritor) {
if(*ritor == keyboard_focus_) {
continue;
}
(**ritor).key_press(*this, handled,
event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
}
}

View file

@ -56,6 +56,12 @@ public:
void mouse_capture(const bool capture = true);
void keyboard_capture(twidget* widget) { keyboard_focus_ = widget; }
/** Adds the widget to the chain, widgets may only be added once. */
void add_to_keyboard_chain(twidget* widget);
/** Remove the widget (if in the vector) from the chain. */
void remove_from_keyboard_chain(twidget* widget);
tpoint get_mouse() const;
//! We impement the handling of the tip, but call the do functions
@ -135,8 +141,21 @@ private:
twidget* mouse_focus_;
bool mouse_captured_;
/** The widget that holds the keyboard focus. */
twidget* keyboard_focus_;
/**
* Fall back keyboard focus items.
*
* When the focussed widget didn't handle the keyboard event (or no handler
* for the keyboard focus) it is send all widgets in this vector. The order
* is from rbegin() to rend(). If the keyboard_focus_ is in the vector it
* won't get the event twice. The first item added to the vector should be
* the window, so it will be the last handler and can dispatch the hotkeys
* registered.
*/
std::vector<twidget*> keyboard_focus_chain_;
void mouse_enter(const SDL_Event& event, twidget* mouse_over);
void mouse_move(const SDL_Event& event, twidget* mouse_over);
void mouse_hover(const SDL_Event& event, twidget* mouse_over);

View file

@ -307,6 +307,7 @@ twindow build(CVideo& video, const std::string& type)
}
window.recalculate_size();
window.add_to_keyboard_chain(&window);
return window;
}