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");
|
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"
|
// clipboard events: "copy-clipboard", "cut-clipboard", "paste-clipboard"
|
||||||
@@ -210,9 +222,24 @@ public:
|
|||||||
// for wxTextAutoCompleteFixed.
|
// for wxTextAutoCompleteFixed.
|
||||||
virtual bool ChangeCompleter(wxTextCompleter* completer) = 0;
|
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()
|
void DisableCompletion()
|
||||||
{
|
{
|
||||||
gtk_entry_set_completion (GetGtkEntry(), NULL);
|
gtk_entry_set_completion (GetGtkEntry(), NULL);
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_data(GetGtkEntry(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~wxTextAutoCompleteData()
|
virtual ~wxTextAutoCompleteData()
|
||||||
@@ -232,12 +259,17 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
explicit wxTextAutoCompleteData(wxTextEntry* entry)
|
explicit wxTextAutoCompleteData(wxTextEntry* entry)
|
||||||
: m_entry(entry)
|
: m_entry(entry),
|
||||||
|
m_origWinFlags(GetEditableWindow(m_entry)->GetWindowStyleFlag())
|
||||||
{
|
{
|
||||||
GtkEntryCompletion* const completion = gtk_entry_completion_new();
|
GtkEntryCompletion* const completion = gtk_entry_completion_new();
|
||||||
|
|
||||||
gtk_entry_completion_set_text_column (completion, 0);
|
gtk_entry_completion_set_text_column (completion, 0);
|
||||||
gtk_entry_set_completion (GetGtkEntry(), completion);
|
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
|
// Provide access to wxTextEntry::GetEditableWindow() to the derived
|
||||||
@@ -270,6 +302,9 @@ protected:
|
|||||||
// The text entry we're associated with.
|
// The text entry we're associated with.
|
||||||
wxTextEntry * const m_entry;
|
wxTextEntry * const m_entry;
|
||||||
|
|
||||||
|
// The original flags of the associated wxTextEntry.
|
||||||
|
const long m_origWinFlags;
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxTextAutoCompleteData);
|
wxDECLARE_NO_COPY_CLASS(wxTextAutoCompleteData);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -410,6 +445,33 @@ private:
|
|||||||
wxDECLARE_NO_COPY_CLASS(wxTextAutoCompleteDynamic);
|
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
|
// wxTextEntry implementation
|
||||||
|
Reference in New Issue
Block a user