From 2933f70a8bc80a12097fac5ae9e63e4a34005121 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 18 Jul 2010 11:53:04 +0000 Subject: [PATCH] Don't reuse the same event object for multiple events in wxGTK. The old code simply called SetEventType() to change the type of the event and called HandleWindowEvent() again with it. This was incorrect as the event was modified after being processed the first time, notably its WasProcessed() flag was set and so wxApp::FilterEvent() wasn't called when it was being processed the second time. In practice this meant that FilterEvent() was never called for wxEVT_CHAR events -- for which it's nevertheless very useful to have as it allows to implement application-wide keyboard processing. Also refactor the code to avoid duplication, exactly the same event sending code was used in gtk_window_key_press_callback() and gtk_wxwindow_commit_cb(). Extract it now in a private SendCharHookAndCharEvents() function. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65005 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/gtk/window.cpp | 66 +++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 209f7be819..eb4d2df8cd 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -822,6 +822,37 @@ struct wxGtkIMData } }; +namespace +{ + +// Send wxEVT_CHAR_HOOK event to the parent of the window and if it wasn't +// processed, send wxEVT_CHAR to the window itself. Return true if either of +// them was handled. +bool +SendCharHookAndCharEvents(const wxKeyEvent& event, wxWindow *win) +{ + // wxEVT_CHAR_HOOK must be sent to the top level parent window to allow it + // to handle key events in all of its children. + wxWindow * const parent = wxGetTopLevelParent(win); + if ( parent ) + { + // We need to make a copy of the event object because it is + // modified while it's handled, notably its WasProcessed() flag + // is set after it had been processed once. + wxKeyEvent eventCharHook(event); + eventCharHook.SetEventType(wxEVT_CHAR_HOOK); + if ( parent->HandleWindowEvent(eventCharHook) ) + return true; + } + + // As above, make a copy of the event first. + wxKeyEvent eventChar(event); + eventChar.SetEventType(wxEVT_CHAR); + return win->HandleWindowEvent(eventChar); +} + +} // anonymous namespace + extern "C" { static gboolean gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), @@ -938,21 +969,7 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), #endif } - // Implement OnCharHook by checking ancestor top level windows - wxWindow *parent = win; - while (parent && !parent->IsTopLevel()) - parent = parent->GetParent(); - if (parent) - { - event.SetEventType( wxEVT_CHAR_HOOK ); - ret = parent->HandleWindowEvent( event ); - } - - if (!ret) - { - event.SetEventType(wxEVT_CHAR); - ret = win->HandleWindowEvent( event ); - } + ret = SendCharHookAndCharEvents(event, win); } } @@ -984,13 +1001,6 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context), if( data.empty() ) return; - bool ret = false; - - // Implement OnCharHook by checking ancestor top level windows - wxWindow *parent = window; - while (parent && !parent->IsTopLevel()) - parent = parent->GetParent(); - for( wxString::const_iterator pstr = data.begin(); pstr != data.end(); ++pstr ) { #if wxUSE_UNICODE @@ -1018,17 +1028,7 @@ gtk_wxwindow_commit_cb (GtkIMContext * WXUNUSED(context), #endif } - if (parent) - { - event.SetEventType( wxEVT_CHAR_HOOK ); - ret = parent->HandleWindowEvent( event ); - } - - if (!ret) - { - event.SetEventType(wxEVT_CHAR); - ret = window->HandleWindowEvent( event ); - } + SendCharHookAndCharEvents(event, window); } } } -- 2.47.2