Avoid wxEVT_TEXT_ENTER when completion popup is shown in wxGTK
For consistency with wxMSW, and also because it just makes more sense from UI point of view, avoid generating wxEVT_TEXT_ENTER events when an auto-completion popup is shown and just accept the current selection in it when Enter is pressed instead. This notably allows to use "Enter" naturally with wxSearchCtrl using auto-completion, instead of generating wxEVT_SEARCH events when the user just wants to select a popup entry. Use grab-notify signal as an indirect way of determining whether the completion popup is currently shown, as there doesn't seem to be any way to obtain its state directly from GTK+. See https://github.com/wxWidgets/wxWidgets/pull/729
This commit is contained in:
@@ -148,7 +148,19 @@ wx_gtk_insert_text_callback(GtkEditable *editable,
|
||||
g_signal_stop_emission_by_name (editable, "insert_text");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GTK+ does not expose any mechanism that we can really rely on to detect if/when
|
||||
// the completion popup is shown or hidden. And the sole reliable way (for now) to
|
||||
// know its state is to connect to the "grab-notify" signal and be notified then
|
||||
// for its state. this is the best we can do for now than any other alternative.
|
||||
// (GtkEntryCompletion grabs/ungrabs keyboard and mouse events on popups/popdowns).
|
||||
|
||||
static void
|
||||
wx_gtk_entry_parent_grab_notify (GtkWidget *widget,
|
||||
gboolean was_grabbed,
|
||||
wxTextAutoCompleteData *data);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// clipboard events: "copy-clipboard", "cut-clipboard", "paste-clipboard"
|
||||
@@ -210,9 +222,24 @@ public:
|
||||
// for wxTextAutoCompleteFixed.
|
||||
virtual bool ChangeCompleter(wxTextCompleter* completer) = 0;
|
||||
|
||||
// We should toggle off wxTE_PROCESS_ENTER flag of our wxTextEntry while
|
||||
// the completion popup is shown to let it see Enter event and process it
|
||||
// on its own (e.g. to dismiss itself). This is done by "grab-notify" signal
|
||||
// see wxTextCtrl::OnChar()
|
||||
void ToggleProcessEnterFlag(bool toggleOff)
|
||||
{
|
||||
long flags = m_origWinFlags;
|
||||
if ( toggleOff )
|
||||
flags &= ~wxTE_PROCESS_ENTER;
|
||||
|
||||
GetEditableWindow(m_entry)->SetWindowStyleFlag(flags);
|
||||
}
|
||||
|
||||
void DisableCompletion()
|
||||
{
|
||||
gtk_entry_set_completion (GetGtkEntry(), NULL);
|
||||
|
||||
g_signal_handlers_disconnect_by_data(GetGtkEntry(), this);
|
||||
}
|
||||
|
||||
virtual ~wxTextAutoCompleteData()
|
||||
@@ -232,12 +259,17 @@ protected:
|
||||
}
|
||||
|
||||
explicit wxTextAutoCompleteData(wxTextEntry* entry)
|
||||
: m_entry(entry)
|
||||
: m_entry(entry),
|
||||
m_origWinFlags(GetEditableWindow(m_entry)->GetWindowStyleFlag())
|
||||
{
|
||||
GtkEntryCompletion* const completion = gtk_entry_completion_new();
|
||||
|
||||
gtk_entry_completion_set_text_column (completion, 0);
|
||||
gtk_entry_set_completion (GetGtkEntry(), completion);
|
||||
|
||||
g_signal_connect (GTK_WIDGET(GetGtkEntry()), "grab-notify",
|
||||
G_CALLBACK (wx_gtk_entry_parent_grab_notify),
|
||||
this);
|
||||
}
|
||||
|
||||
// Provide access to wxTextEntry::GetEditableWindow() to the derived
|
||||
@@ -270,6 +302,9 @@ protected:
|
||||
// The text entry we're associated with.
|
||||
wxTextEntry * const m_entry;
|
||||
|
||||
// The original flags of the associated wxTextEntry.
|
||||
const long m_origWinFlags;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxTextAutoCompleteData);
|
||||
};
|
||||
|
||||
@@ -410,6 +445,33 @@ private:
|
||||
wxDECLARE_NO_COPY_CLASS(wxTextAutoCompleteDynamic);
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
static void
|
||||
wx_gtk_entry_parent_grab_notify (GtkWidget *widget,
|
||||
gboolean was_grabbed,
|
||||
wxTextAutoCompleteData *data)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_ENTRY(widget));
|
||||
|
||||
bool toggleOff = false;
|
||||
|
||||
if ( gtk_widget_has_focus(widget) )
|
||||
{
|
||||
// If was_grabbed is FALSE that means the topmost grab widget ancestor
|
||||
// of our GtkEntry becomes shadowed by a call to gtk_grab_add()
|
||||
// which means that the GtkEntryCompletion popup window is actually
|
||||
// shown on screen.
|
||||
|
||||
if ( !was_grabbed )
|
||||
toggleOff = true;
|
||||
}
|
||||
|
||||
data->ToggleProcessEnterFlag(toggleOff);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
// ============================================================================
|
||||
// wxTextEntry implementation
|
||||
|
Reference in New Issue
Block a user