Fix wxTextCtrl using hints and handling wxEVT_TEXT in wxGTK2 etc

With the generic hint support (used in pre-Vista wxMSW, wxGTK2, ...),
defining a wxEVT_TEXT handler not skipping the event completely broke
the control functionality as it was cleared, i.e. replaced the
user-entered text with the hint, whenever it lost focus.

This happened because wxTextEntryHintData::OnTextChanged() was never
called in this case, as the user-defined wxEVT_TEXT handler preempted
it. Work around this by pushing an event handler to the front of the
window event handlers chain instead of just binding to the window events
directly -- this could still potentially result in the same problem if
the user code pushes their own event handler, but this should be much
more rare and, in any case, there is not much we can do about this (the
only solution would seem to be to modify all platform-specific code to
update wxTextEntryHintData explicitly whenever the text changes).
This commit is contained in:
Vadim Zeitlin
2019-07-08 10:28:10 +02:00
parent 4a6f16cf15
commit 8a4fc479e0

View File

@@ -38,7 +38,7 @@
// wxTextEntryHintData
// ----------------------------------------------------------------------------
class WXDLLIMPEXP_CORE wxTextEntryHintData
class WXDLLIMPEXP_CORE wxTextEntryHintData : public wxEvtHandler
{
public:
wxTextEntryHintData(wxTextEntryBase *entry, wxWindow *win)
@@ -46,16 +46,26 @@ public:
m_win(win),
m_text(m_entry->GetValue())
{
win->Bind(wxEVT_SET_FOCUS, &wxTextEntryHintData::OnSetFocus, this);
win->Bind(wxEVT_KILL_FOCUS, &wxTextEntryHintData::OnKillFocus, this);
win->Bind(wxEVT_TEXT, &wxTextEntryHintData::OnTextChanged, this);
// We push ourselves as the event handler because this allows us to
// handle events before the user-defined handlers and notably process
// wxEVT_TEXT even if the user code already handles it, which is vital
// as if we don't get this event, we would always set the control text
// to the hint when losing focus, instead of preserving the text
// entered by user. Of course, the same problem could still happen if
// the user code pushed their own event handler before this one and
// didn't skip wxEVT_TEXT in it, but there doesn't seem anything we can
// do about this anyhow and this at least takes care of the much more
// common case.
m_win->PushEventHandler(this);
Bind(wxEVT_SET_FOCUS, &wxTextEntryHintData::OnSetFocus, this);
Bind(wxEVT_KILL_FOCUS, &wxTextEntryHintData::OnKillFocus, this);
Bind(wxEVT_TEXT, &wxTextEntryHintData::OnTextChanged, this);
}
~wxTextEntryHintData()
{
m_win->Unbind(wxEVT_SET_FOCUS, &wxTextEntryHintData::OnSetFocus, this);
m_win->Unbind(wxEVT_KILL_FOCUS, &wxTextEntryHintData::OnKillFocus, this);
m_win->Unbind(wxEVT_TEXT, &wxTextEntryHintData::OnTextChanged, this);
m_win->PopEventHandler();
}
// Get the real text of the control such as it was before we replaced it