(svn r24774) -Fix: Invert the focus handling of the OSK. Keep the focus at the OSK and close it on losing focus. This makes the editbox in the OSK behave correctly.

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
frosch 12 years ago
parent bfba90f864
commit 5dfd5e58ee

@ -706,16 +706,9 @@ void GuiShowTooltips(Window *parent, StringID str, uint paramcount, const uint64
new TooltipsWindow(parent, str, paramcount, params, close_tooltip);
}
bool QueryString::HasEditBoxFocus(const Window *w, int wid) const
{
if (w->IsWidgetGloballyFocused(wid)) return true;
if (w->window_class != WC_OSK || _focused_window != w->parent) return false;
return w->parent->nested_focus != NULL && w->parent->nested_focus->type == WWT_EDITBOX;
}
HandleEditBoxResult QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, EventState &state)
{
if (!QueryString::HasEditBoxFocus(w, wid)) return HEBR_NOT_FOCUSED;
if (!w->IsWidgetGloballyFocused(wid)) return HEBR_NOT_FOCUSED;
state = ES_HANDLED;
@ -757,24 +750,19 @@ HandleEditBoxResult QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key
} else {
state = ES_NOT_HANDLED;
}
break;
}
Window *osk = FindWindowById(WC_OSK, 0);
if (osk != NULL && osk->parent == w) osk->InvalidateData();
return edited ? HEBR_EDITING : HEBR_CURSOR;
}
void QueryString::HandleEditBox(Window *w, int wid)
{
if (HasEditBoxFocus(w, wid) && this->text.HandleCaret()) {
if (w->IsWidgetGloballyFocused(wid) && this->text.HandleCaret()) {
w->SetWidgetDirty(wid);
/* When we're not the OSK, notify 'our' OSK to redraw the widget,
* so the caret changes appropriately. */
if (w->window_class != WC_OSK) {
Window *w_osk = FindWindowById(WC_OSK, 0);
if (w_osk != NULL && w_osk->parent == w) w_osk->InvalidateData();
}
/* For the OSK also invalidate the parent window */
if (w->window_class == WC_OSK) w->InvalidateData();
}
}
@ -818,7 +806,8 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs;
DrawString(delta, tb->pixels, 0, tb->buf, TC_YELLOW);
if (HasEditBoxFocus(w, wid) && tb->caret) {
bool focussed = w->IsWidgetGloballyFocused(wid) || IsOSKOpenedFor(w, wid);
if (focussed && tb->caret) {
int caret_width = GetStringBoundingBox("_").width;
DrawString(tb->caretxoffs + delta, tb->caretxoffs + delta + caret_width, 0, "_", TC_WHITE);
}

@ -53,11 +53,13 @@ struct OskWindow : public Window {
this->caption = (par_wid->widget_data != STR_NULL) ? par_wid->widget_data : this->qs->caption;
this->text_btn = button;
this->text = &this->qs->text;
this->querystrings[WID_OSK_TEXT] = this->qs;
/* make a copy in case we need to reset later */
this->orig_str_buf = strdup(this->qs->text.buf);
this->InitNested(desc, 0);
this->SetFocusedWidget(WID_OSK_TEXT);
/* Not needed by default. */
this->DisableWidget(WID_OSK_SPECIAL);
@ -105,13 +107,6 @@ struct OskWindow : public Window {
TC_BLACK);
}
virtual void OnPaint()
{
this->DrawWidgets();
this->qs->DrawEditBox(this, WID_OSK_TEXT);
}
virtual void OnClick(Point pt, int widget, int click_count)
{
/* clicked a letter */
@ -127,9 +122,6 @@ struct OskWindow : public Window {
this->UpdateOskState();
this->SetDirty();
}
/* Return focus to the parent widget and window. */
this->parent->SetFocusedWidget(this->text_btn);
SetFocusedWindow(this->parent);
return;
}
@ -195,9 +187,6 @@ struct OskWindow : public Window {
}
break;
}
/* Return focus to the parent widget and window. */
this->parent->SetFocusedWidget(this->text_btn);
SetFocusedWindow(this->parent);
}
virtual void OnEditboxChanged(int widget)
@ -207,24 +196,17 @@ struct OskWindow : public Window {
this->parent->SetWidgetDirty(this->text_btn);
}
virtual void OnMouseLoop()
{
this->qs->HandleEditBox(this, WID_OSK_TEXT);
/* make the caret of the parent window also blink */
this->parent->SetWidgetDirty(this->text_btn);
}
/**
* Some data on this window has become invalid.
* @param data Information about the changed data.
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
*/
virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
{
if (!gui_scope) return;
this->SetWidgetDirty(WID_OSK_TEXT);
this->parent->SetWidgetDirty(this->text_btn);
}
virtual void OnFocusLost()
{
delete this;
}
};
static const int HALF_KEY_WIDTH = 7; // Width of 1/2 key in pixels.
@ -448,3 +430,15 @@ void UpdateOSKOriginalText(const Window *parent, int button)
osk->SetDirty();
}
/**
* Check whether the OSK is opened for a specific editbox.
* @parent w Window to check for
* @param button Editbox of \a w to check for
* @return true if the OSK is oppened for \a button.
*/
bool IsOSKOpenedFor(const Window *w, int button)
{
OskWindow *osk = dynamic_cast<OskWindow *>(FindWindowById(WC_OSK, 0));
return osk != NULL && osk->parent == w && osk->text_btn == button;
}

@ -62,8 +62,6 @@ struct QueryString {
free(this->orig);
}
private:
bool HasEditBoxFocus(const Window *w, int wid) const;
public:
void DrawEditBox(const Window *w, int wid) const;
void ClickEditBox(Window *w, Point pt, int wid, int click_count, bool focus_changed);
@ -73,5 +71,6 @@ public:
void ShowOnScreenKeyboard(Window *parent, int button);
void UpdateOSKOriginalText(const Window *parent, int button);
bool IsOSKOpenedFor(const Window *w, int button);
#endif /* QUERYSTRING_GUI_H */

@ -422,12 +422,6 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count)
(w->desc_flags & WDF_NO_FOCUS) == 0 && // Don't lose focus to toolbars
widget_type != WWT_CLOSEBOX) { // Don't change focused window if 'X' (close button) was clicked
focused_widget_changed = true;
if (_focused_window != NULL) {
_focused_window->OnFocusLost();
/* The window that lost focus may have had opened a OSK, window so close it, unless the user has clicked on the OSK window. */
if (w->window_class != WC_OSK) DeleteWindowById(WC_OSK, 0);
}
SetFocusedWindow(w);
w->OnFocus();
}
@ -440,13 +434,9 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count)
int widget_index = nw->index; ///< Index of the widget
/* Clicked on a widget that is not disabled.
* So unless the clicked widget is the caption bar, change focus to this widget */
if (widget_type != WWT_CAPTION) {
/* Close the OSK window if a edit box loses focus */
if (w->nested_focus != NULL && w->nested_focus->type == WWT_EDITBOX && w->nested_focus != nw && w->window_class != WC_OSK) {
DeleteWindowById(WC_OSK, 0);
}
* So unless the clicked widget is the caption bar, change focus to this widget.
* Exception: In the OSK we always want the editbox to stay focussed. */
if (widget_type != WWT_CAPTION && w->window_class != WC_OSK) {
/* focused_widget_changed is 'now' only true if the window this widget
* is in gained focus. In that case it must remain true, also if the
* local widget focus did not change. As such it's the logical-or of
@ -1199,10 +1189,10 @@ void Window::InitializeData(const WindowDesc *desc, WindowNumber window_number)
this->resize.step_width = this->nested_root->resize_x;
this->resize.step_height = this->nested_root->resize_y;
/* Give focus to the opened window unless it is the OSK window or a text box
/* Give focus to the opened window unless a text box
* of focused window has focus (so we don't interrupt typing). But if the new
* window has a text box, then take focus anyway. */
if (this->window_class != WC_OSK && (!EditBoxInGlobalFocus() || this->nested_root->GetWidgetOfType(WWT_EDITBOX) != NULL)) SetFocusedWindow(this);
if (!EditBoxInGlobalFocus() || this->nested_root->GetWidgetOfType(WWT_EDITBOX) != NULL) SetFocusedWindow(this);
/* Insert the window into the correct location in the z-ordering. */
AddWindowToZOrdering(this);
@ -2275,10 +2265,14 @@ EventState Window::HandleEditBoxKey(int wid, uint16 key, uint16 keycode)
case HEBR_CURSOR:
this->SetWidgetDirty(wid);
/* For the OSK also invalidate the parent window */
if (this->window_class == WC_OSK) this->InvalidateData();
break;
case HEBR_CONFIRM:
if (query->ok_button >= 0) {
if (this->window_class == WC_OSK) {
this->OnClick(Point(), WID_OSK_OK, 1);
} else if (query->ok_button >= 0) {
this->OnClick(Point(), query->ok_button, 1);
} else {
action = query->ok_button;
@ -2286,7 +2280,9 @@ EventState Window::HandleEditBoxKey(int wid, uint16 key, uint16 keycode)
break;
case HEBR_CANCEL:
if (query->cancel_button >= 0) {
if (this->window_class == WC_OSK) {
this->OnClick(Point(), WID_OSK_CANCEL, 1);
} else if (query->cancel_button >= 0) {
this->OnClick(Point(), query->cancel_button, 1);
} else {
action = query->cancel_button;

Loading…
Cancel
Save