Merge branch 'gtk-text-changed-coalesce'
Harmonize wxEVT_TEXT events in wxGTK with other ports. Also use IME for wxComboBox in wxGTK too. See https://github.com/wxWidgets/wxWidgets/pull/1400
This commit is contained in:
@@ -145,13 +145,16 @@ protected:
|
||||
virtual GtkEntry *GetEntry() const wxOVERRIDE
|
||||
{ return m_entry; }
|
||||
|
||||
virtual int GTKIMFilterKeypress(GdkEventKey* event) const wxOVERRIDE
|
||||
{ return GTKEntryIMFilterKeypress(event); }
|
||||
|
||||
|
||||
GtkEntry* m_entry;
|
||||
|
||||
private:
|
||||
// From wxTextEntry:
|
||||
virtual wxWindow *GetEditableWindow() wxOVERRIDE { return this; }
|
||||
virtual GtkEditable *GetEditable() const wxOVERRIDE;
|
||||
virtual void EnableTextChangedEvents(bool enable) wxOVERRIDE;
|
||||
|
||||
void Init();
|
||||
|
||||
|
@@ -142,6 +142,8 @@ public:
|
||||
static wxVisualAttributes
|
||||
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
|
||||
|
||||
void GTKOnTextChanged() wxOVERRIDE;
|
||||
|
||||
protected:
|
||||
// overridden wxWindow virtual methods
|
||||
virtual wxSize DoGetBestSize() const wxOVERRIDE;
|
||||
@@ -182,7 +184,6 @@ private:
|
||||
// overridden wxTextEntry virtual methods
|
||||
virtual GtkEditable *GetEditable() const wxOVERRIDE;
|
||||
virtual GtkEntry *GetEntry() const wxOVERRIDE;
|
||||
virtual void EnableTextChangedEvents(bool enable) wxOVERRIDE;
|
||||
|
||||
// change the font for everything in this control
|
||||
void ChangeFontGlobally();
|
||||
@@ -196,7 +197,7 @@ private:
|
||||
// returns either m_text or m_buffer depending on whether the control is
|
||||
// single- or multi-line; convenient for the GTK+ functions which work with
|
||||
// both
|
||||
void *GetTextObject() const
|
||||
void *GetTextObject() const wxOVERRIDE
|
||||
{
|
||||
return IsMultiLine() ? static_cast<void *>(m_buffer)
|
||||
: static_cast<void *>(m_text);
|
||||
|
@@ -15,6 +15,7 @@ typedef struct _GtkEditable GtkEditable;
|
||||
typedef struct _GtkEntry GtkEntry;
|
||||
|
||||
class wxTextAutoCompleteData; // private class used only by wxTextEntry itself
|
||||
class wxTextCoalesceData; // another private class
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxTextEntry: roughly corresponds to GtkEditable
|
||||
@@ -62,6 +63,16 @@ public:
|
||||
bool GTKEntryOnInsertText(const char* text);
|
||||
bool GTKIsUpperCase() const { return m_isUpperCase; }
|
||||
|
||||
// Called from "changed" signal handler (or, possibly, slightly later, when
|
||||
// coalescing several "changed" signals into a single event) for GtkEntry.
|
||||
//
|
||||
// By default just generates a wxEVT_TEXT, but overridden to do more things
|
||||
// in wxTextCtrl.
|
||||
virtual void GTKOnTextChanged() { SendTextUpdatedEvent(); }
|
||||
|
||||
// Helper functions only used internally.
|
||||
wxTextCoalesceData* GTKGetCoalesceData() const { return m_coalesceData; }
|
||||
|
||||
protected:
|
||||
// This method must be called from the derived class Create() to connect
|
||||
// the handlers for the clipboard (cut/copy/paste) events.
|
||||
@@ -70,6 +81,10 @@ protected:
|
||||
// And this one to connect "insert-text" signal.
|
||||
void GTKConnectInsertTextSignal(GtkEntry* entry);
|
||||
|
||||
// Finally this one connects to the "changed" signal on the object returned
|
||||
// by GetTextObject().
|
||||
void GTKConnectChangedSignal();
|
||||
|
||||
|
||||
virtual void DoSetValue(const wxString& value, int flags) wxOVERRIDE;
|
||||
virtual wxString DoGetValue() const wxOVERRIDE;
|
||||
@@ -81,11 +96,24 @@ protected:
|
||||
virtual bool DoAutoCompleteStrings(const wxArrayString& choices) wxOVERRIDE;
|
||||
virtual bool DoAutoCompleteCustom(wxTextCompleter *completer) wxOVERRIDE;
|
||||
|
||||
// Override the base class method to use GtkEntry IM context.
|
||||
virtual int GTKIMFilterKeypress(GdkEventKey* event) const;
|
||||
// Call this from the overridden wxWindow::GTKIMFilterKeypress() to use
|
||||
// GtkEntry IM context.
|
||||
int GTKEntryIMFilterKeypress(GdkEventKey* event) const;
|
||||
|
||||
// If GTKEntryIMFilterKeypress() is not called (as multiline wxTextCtrl
|
||||
// uses its own IM), call this method instead to still notify wxTextEntry
|
||||
// about the key press events in the given widget.
|
||||
void GTKEntryOnKeypress(GtkWidget* widget) const;
|
||||
|
||||
|
||||
static int GTKGetEntryTextLength(GtkEntry* entry);
|
||||
|
||||
// Block/unblock the corresponding GTK signal.
|
||||
//
|
||||
// Note that we make it protected in wxGTK as it is called from wxComboBox
|
||||
// currently.
|
||||
virtual void EnableTextChangedEvents(bool enable) wxOVERRIDE;
|
||||
|
||||
private:
|
||||
// implement this to return the associated GtkEntry or another widget
|
||||
// implementing GtkEditable
|
||||
@@ -94,6 +122,12 @@ private:
|
||||
// implement this to return the associated GtkEntry
|
||||
virtual GtkEntry *GetEntry() const = 0;
|
||||
|
||||
// This one exists in order to be overridden by wxTextCtrl which uses
|
||||
// either GtkEditable or GtkTextBuffer depending on whether it is single-
|
||||
// or multi-line.
|
||||
virtual void *GetTextObject() const { return GetEntry(); }
|
||||
|
||||
|
||||
// Various auto-completion-related stuff, only used if any of AutoComplete()
|
||||
// methods are called.
|
||||
wxTextAutoCompleteData *m_autoCompleteData;
|
||||
@@ -101,6 +135,10 @@ private:
|
||||
// It needs to call our GetEntry() method.
|
||||
friend class wxTextAutoCompleteData;
|
||||
|
||||
// Data used for coalescing "changed" events resulting from a single user
|
||||
// action.
|
||||
mutable wxTextCoalesceData* m_coalesceData;
|
||||
|
||||
bool m_isUpperCase;
|
||||
};
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "wx/bitmap.h"
|
||||
#include "wx/button.h"
|
||||
#include "wx/checkbox.h"
|
||||
#include "wx/dcclient.h"
|
||||
#include "wx/radiobox.h"
|
||||
#include "wx/statbox.h"
|
||||
#include "wx/stattext.h"
|
||||
@@ -986,19 +987,21 @@ void TextWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
|
||||
(m_radioWrap->GetSelection() != DEFAULTS.wrapStyle) );
|
||||
}
|
||||
|
||||
void TextWidgetsPage::OnText(wxCommandEvent& WXUNUSED(event))
|
||||
void TextWidgetsPage::OnText(wxCommandEvent& event)
|
||||
{
|
||||
// small hack to suppress the very first message: by then the logging is
|
||||
// not yet redirected and so initial setting of the text value results in
|
||||
// an annoying message box
|
||||
static bool s_firstTime = true;
|
||||
if ( s_firstTime )
|
||||
{
|
||||
s_firstTime = false;
|
||||
if ( !IsUsingLogWindow() )
|
||||
return;
|
||||
}
|
||||
|
||||
wxLogMessage("Text ctrl value changed");
|
||||
// Replace middle of long text with ellipsis just to avoid filling up the
|
||||
// log control with too much unnecessary stuff.
|
||||
wxLogMessage("Text control value changed (now '%s')",
|
||||
wxControl::Ellipsize
|
||||
(
|
||||
event.GetString(),
|
||||
wxClientDC(this),
|
||||
wxELLIPSIZE_MIDDLE,
|
||||
GetTextExtent('W').x*100
|
||||
));
|
||||
}
|
||||
|
||||
void TextWidgetsPage::OnTextEnter(wxCommandEvent& event)
|
||||
|
@@ -139,6 +139,13 @@ const wxChar *WidgetsCategories[MAX_PAGES] = {
|
||||
class WidgetsApp : public wxApp
|
||||
{
|
||||
public:
|
||||
WidgetsApp()
|
||||
{
|
||||
#if USE_LOG
|
||||
m_logTarget = NULL;
|
||||
#endif // USE_LOG
|
||||
}
|
||||
|
||||
// override base class virtuals
|
||||
// ----------------------------
|
||||
|
||||
@@ -146,8 +153,20 @@ public:
|
||||
// initialization (doing it here and not in the ctor allows to have an error
|
||||
// return: if OnInit() returns false, the application terminates)
|
||||
virtual bool OnInit() wxOVERRIDE;
|
||||
|
||||
// real implementation of WidgetsPage method with the same name
|
||||
bool IsUsingLogWindow() const;
|
||||
|
||||
private:
|
||||
#if USE_LOG
|
||||
wxLog* m_logTarget;
|
||||
#endif // USE_LOG
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(WidgetsApp);
|
||||
};
|
||||
|
||||
wxDECLARE_APP(WidgetsApp); // This provides a convenient wxGetApp() accessor.
|
||||
|
||||
// Define a new frame type: this is going to be our main frame
|
||||
class WidgetsFrame : public wxFrame
|
||||
{
|
||||
@@ -375,9 +394,22 @@ bool WidgetsApp::OnInit()
|
||||
wxFrame *frame = new WidgetsFrame(title + " widgets demo");
|
||||
frame->Show();
|
||||
|
||||
#if USE_LOG
|
||||
m_logTarget = wxLog::GetActiveTarget();
|
||||
#endif // USE_LOG
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WidgetsApp::IsUsingLogWindow() const
|
||||
{
|
||||
#if USE_LOG
|
||||
return wxLog::GetActiveTarget() == m_logTarget;
|
||||
#else // !USE_LOG
|
||||
return false;
|
||||
#endif // USE_LOG
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// WidgetsFrame construction
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -1200,8 +1232,13 @@ void WidgetsFrame::OnSetHint(wxCommandEvent& WXUNUSED(event))
|
||||
|
||||
void WidgetsFrame::OnWidgetFocus(wxFocusEvent& event)
|
||||
{
|
||||
wxLogMessage("Widgets %s focus",
|
||||
event.GetEventType() == wxEVT_SET_FOCUS ? "got" : "lost");
|
||||
// Don't show annoying message boxes when starting or closing the sample,
|
||||
// only log these events in our own logger.
|
||||
if ( wxGetApp().IsUsingLogWindow() )
|
||||
{
|
||||
wxLogMessage("Widgets %s focus",
|
||||
event.GetEventType() == wxEVT_SET_FOCUS ? "got" : "lost");
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
@@ -1384,3 +1421,9 @@ wxCheckBox *WidgetsPage::CreateCheckBoxAndAddToSizer(wxSizer *sizer,
|
||||
|
||||
return checkbox;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool WidgetsPage::IsUsingLogWindow()
|
||||
{
|
||||
return wxGetApp().IsUsingLogWindow();
|
||||
}
|
||||
|
@@ -155,6 +155,10 @@ public:
|
||||
// the default attributes for the widget
|
||||
static WidgetAttributes& GetAttrs();
|
||||
|
||||
// return true if we're showing logs in the log window (always the case
|
||||
// except during startup and shutdown)
|
||||
static bool IsUsingLogWindow();
|
||||
|
||||
protected:
|
||||
// several helper functions for page creation
|
||||
|
||||
|
@@ -27,14 +27,6 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern "C" {
|
||||
static void
|
||||
gtkcombobox_text_changed_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
|
||||
{
|
||||
wxCommandEvent event( wxEVT_TEXT, combo->GetId() );
|
||||
event.SetString( combo->GetValue() );
|
||||
event.SetEventObject( combo );
|
||||
combo->HandleWindowEvent( event );
|
||||
}
|
||||
|
||||
static void
|
||||
gtkcombobox_changed_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
|
||||
@@ -185,9 +177,7 @@ bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value,
|
||||
gtk_entry_set_text( entry, wxGTK_CONV(value) );
|
||||
}
|
||||
|
||||
g_signal_connect_after (entry, "changed",
|
||||
G_CALLBACK (gtkcombobox_text_changed_callback), this);
|
||||
|
||||
GTKConnectChangedSignal();
|
||||
GTKConnectInsertTextSignal(entry);
|
||||
GTKConnectClipboardSignals(GTK_WIDGET(entry));
|
||||
}
|
||||
@@ -219,7 +209,7 @@ void wxComboBox::GTKCreateComboBoxWidget()
|
||||
|
||||
GtkEditable *wxComboBox::GetEditable() const
|
||||
{
|
||||
return GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(m_widget)));
|
||||
return GTK_EDITABLE(m_entry);
|
||||
}
|
||||
|
||||
void wxComboBox::OnChar( wxKeyEvent &event )
|
||||
@@ -248,23 +238,6 @@ void wxComboBox::OnChar( wxKeyEvent &event )
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void wxComboBox::EnableTextChangedEvents(bool enable)
|
||||
{
|
||||
if ( !GetEntry() )
|
||||
return;
|
||||
|
||||
if ( enable )
|
||||
{
|
||||
g_signal_handlers_unblock_by_func(gtk_bin_get_child(GTK_BIN(m_widget)),
|
||||
(gpointer)gtkcombobox_text_changed_callback, this);
|
||||
}
|
||||
else // disable
|
||||
{
|
||||
g_signal_handlers_block_by_func(gtk_bin_get_child(GTK_BIN(m_widget)),
|
||||
(gpointer)gtkcombobox_text_changed_callback, this);
|
||||
}
|
||||
}
|
||||
|
||||
void wxComboBox::GTKDisableEvents()
|
||||
{
|
||||
EnableTextChangedEvents(false);
|
||||
|
@@ -567,24 +567,6 @@ gtk_textctrl_populate_popup( GtkEntry *WXUNUSED(entry), GtkMenu *menu, wxTextCtr
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "changed"
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern "C" {
|
||||
static void
|
||||
gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
|
||||
{
|
||||
if ( win->IgnoreTextUpdate() )
|
||||
return;
|
||||
|
||||
if ( win->MarkDirtyOnChange() )
|
||||
win->MarkDirty();
|
||||
|
||||
win->SendTextUpdatedEvent();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "mark_set"
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -774,16 +756,7 @@ bool wxTextCtrl::Create( wxWindow *parent,
|
||||
}
|
||||
|
||||
// We want to be notified about text changes.
|
||||
if (multi_line)
|
||||
{
|
||||
g_signal_connect (m_buffer, "changed",
|
||||
G_CALLBACK (gtk_text_changed_callback), this);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_signal_connect (m_text, "changed",
|
||||
G_CALLBACK (gtk_text_changed_callback), this);
|
||||
}
|
||||
GTKConnectChangedSignal();
|
||||
|
||||
// Catch to disable focus out handling
|
||||
g_signal_connect (m_text, "populate_popup",
|
||||
@@ -885,7 +858,11 @@ GtkEntry *wxTextCtrl::GetEntry() const
|
||||
int wxTextCtrl::GTKIMFilterKeypress(GdkEventKey* event) const
|
||||
{
|
||||
if (IsSingleLine())
|
||||
return wxTextEntry::GTKIMFilterKeypress(event);
|
||||
return GTKEntryIMFilterKeypress(event);
|
||||
|
||||
// When not calling GTKEntryIMFilterKeypress(), we need to notify the code
|
||||
// in wxTextEntry about the key presses explicitly.
|
||||
GTKEntryOnKeypress(m_text);
|
||||
|
||||
int result = false;
|
||||
#if GTK_CHECK_VERSION(2, 22, 0)
|
||||
@@ -1371,24 +1348,21 @@ void wxTextCtrl::DiscardEdits()
|
||||
m_modified = false;
|
||||
}
|
||||
|
||||
void wxTextCtrl::GTKOnTextChanged()
|
||||
{
|
||||
if ( IgnoreTextUpdate() )
|
||||
return;
|
||||
|
||||
if ( MarkDirtyOnChange() )
|
||||
MarkDirty();
|
||||
|
||||
SendTextUpdatedEvent();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// event handling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxTextCtrl::EnableTextChangedEvents(bool enable)
|
||||
{
|
||||
if ( enable )
|
||||
{
|
||||
g_signal_handlers_unblock_by_func(GetTextObject(),
|
||||
(gpointer)gtk_text_changed_callback, this);
|
||||
}
|
||||
else // disable events
|
||||
{
|
||||
g_signal_handlers_block_by_func(GetTextObject(),
|
||||
(gpointer)gtk_text_changed_callback, this);
|
||||
}
|
||||
}
|
||||
|
||||
bool wxTextCtrl::IgnoreTextUpdate()
|
||||
{
|
||||
if ( m_countUpdatesToIgnore > 0 )
|
||||
|
@@ -37,6 +37,65 @@
|
||||
#include "wx/gtk/private/object.h"
|
||||
#include "wx/gtk/private/string.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxTextCoalesceData
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxTextCoalesceData
|
||||
{
|
||||
public:
|
||||
wxTextCoalesceData(GtkWidget* widget, gulong handlerAfterKeyPress)
|
||||
: m_handlerAfterKeyPress(handlerAfterKeyPress)
|
||||
{
|
||||
m_inKeyPress = false;
|
||||
m_pendingTextChanged = false;
|
||||
|
||||
// This signal handler is unblocked in StartHandlingKeyPress(), so
|
||||
// we need to block it initially to compensate for this.
|
||||
g_signal_handler_block(widget, m_handlerAfterKeyPress);
|
||||
}
|
||||
|
||||
void StartHandlingKeyPress(GtkWidget* widget)
|
||||
{
|
||||
m_inKeyPress = true;
|
||||
m_pendingTextChanged = false;
|
||||
|
||||
g_signal_handler_unblock(widget, m_handlerAfterKeyPress);
|
||||
}
|
||||
|
||||
bool SetPendingIfInKeyPress()
|
||||
{
|
||||
if ( !m_inKeyPress )
|
||||
return false;
|
||||
|
||||
m_pendingTextChanged = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EndHandlingKeyPressAndCheckIfPending(GtkWidget* widget)
|
||||
{
|
||||
g_signal_handler_block(widget, m_handlerAfterKeyPress);
|
||||
|
||||
wxASSERT( m_inKeyPress );
|
||||
m_inKeyPress = false;
|
||||
|
||||
if ( !m_pendingTextChanged )
|
||||
return false;
|
||||
|
||||
m_pendingTextChanged = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_inKeyPress;
|
||||
bool m_pendingTextChanged;
|
||||
const gulong m_handlerAfterKeyPress;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxTextCoalesceData);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// helper function to get the length of the text
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -57,8 +116,45 @@ static int GetEntryTextLength(GtkEntry* entry)
|
||||
// signal handlers implementation
|
||||
// ============================================================================
|
||||
|
||||
// "insert_text" handler for GtkEntry
|
||||
extern "C" {
|
||||
|
||||
// "event-after" handler is only connected when we get a "key-press-event", so
|
||||
// it's effectively called after the end of processing of this event and used
|
||||
// to send a single wxEVT_TEXT even if we received several (typically two, when
|
||||
// the selected text in the control is replaced by new text) "changed" signals.
|
||||
static gboolean
|
||||
wx_gtk_text_after_key_press(GtkWidget* widget,
|
||||
GdkEventKey* WXUNUSED(gdk_event),
|
||||
wxTextEntry* entry)
|
||||
{
|
||||
wxTextCoalesceData* const data = entry->GTKGetCoalesceData();
|
||||
wxCHECK_MSG( data, FALSE, "must be non-null if this handler is called" );
|
||||
|
||||
if ( data->EndHandlingKeyPressAndCheckIfPending(widget) )
|
||||
{
|
||||
entry->GTKOnTextChanged();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// "changed" handler for GtkEntry
|
||||
static void
|
||||
wx_gtk_text_changed_callback(GtkWidget* WXUNUSED(widget), wxTextEntry* entry)
|
||||
{
|
||||
if ( wxTextCoalesceData* const data = entry->GTKGetCoalesceData() )
|
||||
{
|
||||
if ( data->SetPendingIfInKeyPress() )
|
||||
{
|
||||
// Don't send the event right now as more might be coming.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
entry->GTKOnTextChanged();
|
||||
}
|
||||
|
||||
// "insert_text" handler for GtkEntry
|
||||
static void
|
||||
wx_gtk_insert_text_callback(GtkEditable *editable,
|
||||
const gchar * new_text,
|
||||
@@ -510,11 +606,13 @@ wx_gtk_entry_parent_grab_notify (GtkWidget *widget,
|
||||
wxTextEntry::wxTextEntry()
|
||||
{
|
||||
m_autoCompleteData = NULL;
|
||||
m_coalesceData = NULL;
|
||||
m_isUpperCase = false;
|
||||
}
|
||||
|
||||
wxTextEntry::~wxTextEntry()
|
||||
{
|
||||
delete m_coalesceData;
|
||||
delete m_autoCompleteData;
|
||||
}
|
||||
|
||||
@@ -854,8 +952,38 @@ void wxTextEntry::ForceUpper()
|
||||
// IM handling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int wxTextEntry::GTKIMFilterKeypress(GdkEventKey* event) const
|
||||
void wxTextEntry::GTKEntryOnKeypress(GtkWidget* widget) const
|
||||
{
|
||||
// We coalesce possibly multiple events resulting from a single key press
|
||||
// (this always happens when there is a selection, as we always get a
|
||||
// "changed" event when the selection is removed and another one when the
|
||||
// new text is inserted) into a single wxEVT_TEXT and to do this we need
|
||||
// this extra handler.
|
||||
if ( !m_coalesceData )
|
||||
{
|
||||
// We can't use g_signal_connect_after("key-press-event") because the
|
||||
// emission of this signal is stopped by GtkEntry own key-press-event
|
||||
// handler, so we have to use the generic "event-after" instead to be
|
||||
// notified about the end of handling of this key press and to send any
|
||||
// pending events a.s.a.p.
|
||||
const gulong handler = g_signal_connect
|
||||
(
|
||||
widget,
|
||||
"event-after",
|
||||
G_CALLBACK(wx_gtk_text_after_key_press),
|
||||
const_cast<wxTextEntry*>(this)
|
||||
);
|
||||
|
||||
m_coalesceData = new wxTextCoalesceData(widget, handler);
|
||||
}
|
||||
|
||||
m_coalesceData->StartHandlingKeyPress(widget);
|
||||
}
|
||||
|
||||
int wxTextEntry::GTKEntryIMFilterKeypress(GdkEventKey* event) const
|
||||
{
|
||||
GTKEntryOnKeypress(GTK_WIDGET(GetEntry()));
|
||||
|
||||
int result = false;
|
||||
#if GTK_CHECK_VERSION(2, 22, 0)
|
||||
if (wx_is_at_least_gtk2(22))
|
||||
@@ -869,6 +997,31 @@ int wxTextEntry::GTKIMFilterKeypress(GdkEventKey* event) const
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// signals and events
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxTextEntry::EnableTextChangedEvents(bool enable)
|
||||
{
|
||||
if ( enable )
|
||||
{
|
||||
g_signal_handlers_unblock_by_func(GetTextObject(),
|
||||
(gpointer)wx_gtk_text_changed_callback, this);
|
||||
}
|
||||
else // disable events
|
||||
{
|
||||
g_signal_handlers_block_by_func(GetTextObject(),
|
||||
(gpointer)wx_gtk_text_changed_callback, this);
|
||||
}
|
||||
}
|
||||
|
||||
void wxTextEntry::GTKConnectChangedSignal()
|
||||
{
|
||||
g_signal_connect(GetTextObject(), "changed",
|
||||
G_CALLBACK(wx_gtk_text_changed_callback), this);
|
||||
|
||||
}
|
||||
|
||||
void wxTextEntry::GTKConnectInsertTextSignal(GtkEntry* entry)
|
||||
{
|
||||
g_signal_connect(entry, "insert_text",
|
||||
|
Reference in New Issue
Block a user