Changeset - r19819:048b8ca075ad
[Not reviewed]
master
0 4 0
frosch - 12 years ago 2012-11-28 21:14:28
frosch@openttd.org
(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.
4 files changed with 41 insertions and 63 deletions:
0 comments (0 inline, 0 general)
src/misc_gui.cpp
Show inline comments
 
@@ -706,16 +706,9 @@ void GuiShowTooltips(Window *parent, Str
 
	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::HandleE
 
			} 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 Wind
 
	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);
 
	}
src/osk_gui.cpp
Show inline comments
 
@@ -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 
 

	
 
	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;
 
}
src/querystring_gui.h
Show inline comments
 
@@ -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 */
src/window.cpp
Show inline comments
 
@@ -422,12 +422,6 @@ static void DispatchLeftClickEvent(Windo
 
			(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(Windo
 
	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 Window
 
	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 
 

	
 
		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 
 
			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;
0 comments (0 inline, 0 general)