diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index c9657f804b..bebb83d389 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -100,6 +100,21 @@ static gboolean wxapp_idle_callback(gpointer) } } +// 0: no change, 1: focus in, 2: focus out +static int gs_focusChange; + +extern "C" { +static gboolean +wx_focus_event_hook(GSignalInvocationHint*, unsigned, const GValue* param_values, void* data) +{ + // If focus change on TLW + if (GTK_IS_WINDOW(g_value_peek_pointer(param_values))) + gs_focusChange = GPOINTER_TO_INT(data); + + return true; +} +} + bool wxApp::DoIdle() { guint id_save; @@ -123,6 +138,12 @@ bool wxApp::DoIdle() } gdk_threads_enter(); + + if (gs_focusChange) { + SetActive(gs_focusChange == 1, NULL); + gs_focusChange = 0; + } + bool needMore; do { ProcessPendingEvents(); @@ -415,8 +436,18 @@ bool wxApp::Initialize(int& argc_, wxChar **argv_) wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding()); #endif - // make sure GtkWidget type is loaded, idle hooks need it - g_type_class_ref(GTK_TYPE_WIDGET); + // make sure GtkWidget type is loaded, signal emission hooks need it + const GType widgetType = GTK_TYPE_WIDGET; + g_type_class_ref(widgetType); + + // focus in/out hooks used for generating wxEVT_ACTIVATE_APP + g_signal_add_emission_hook( + g_signal_lookup("focus_in_event", widgetType), + 0, wx_focus_event_hook, GINT_TO_POINTER(1), NULL); + g_signal_add_emission_hook( + g_signal_lookup("focus_out_event", widgetType), + 0, wx_focus_event_hook, GINT_TO_POINTER(2), NULL); + WakeUpIdle(); return true; diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index 016227873b..94c47caff1 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -27,7 +27,6 @@ #include "wx/frame.h" #include "wx/icon.h" #include "wx/log.h" - #include "wx/app.h" #endif #include "wx/evtloop.h" @@ -59,12 +58,6 @@ int wxOpenModalDialogsCount = 0; static wxTopLevelWindowGTK *g_activeFrame = NULL; static wxTopLevelWindowGTK *g_lastActiveFrame = NULL; -// if we detect that the app has got/lost the focus, we set this variable to -// either TRUE or FALSE and an activate event will be sent during the next -// OnIdle() call and it is reset to -1: this value means that we shouldn't -// send any activate events at all -static int g_sendActivateEvent = -1; - extern wxCursor g_globalCursor; extern wxCursor g_busyCursor; @@ -134,20 +127,6 @@ static gboolean gtk_frame_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win ) { - switch ( g_sendActivateEvent ) - { - case -1: - // we've got focus from outside, synthetize wxActivateEvent - g_sendActivateEvent = 1; - break; - - case 0: - // another our window just lost focus, it was already ours before - // - don't send any wxActivateEvent - g_sendActivateEvent = -1; - break; - } - g_activeFrame = win; g_lastActiveFrame = g_activeFrame; @@ -167,7 +146,6 @@ static gboolean gtk_frame_focus_in_callback( GtkWidget *widget, case -2: break; } - wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame); wxActivateEvent event(wxEVT_ACTIVATE, true, g_activeFrame->GetId()); event.SetEventObject(g_activeFrame); g_activeFrame->HandleWindowEvent(event); @@ -186,18 +164,8 @@ gboolean gtk_frame_focus_out_callback(GtkWidget * WXUNUSED(widget), GdkEventFocus *WXUNUSED(gdk_event), wxTopLevelWindowGTK * WXUNUSED(win)) { - // if the focus goes out of our app altogether, OnIdle() will send - // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset - // g_sendActivateEvent to -1 - g_sendActivateEvent = 0; - - // wxASSERT_MSG( (g_activeFrame == win), wxT("TLW deactivatd although it wasn't active") ); - - // wxPrintf( wxT("inactive: %s\n"), win->GetTitle().c_str() ); - if (g_activeFrame) { - wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame); wxActivateEvent event(wxEVT_ACTIVATE, false, g_activeFrame->GetId()); event.SetEventObject(g_activeFrame); g_activeFrame->HandleWindowEvent(event); @@ -1305,20 +1273,6 @@ wxTopLevelWindowGTK::DecorSize& wxTopLevelWindowGTK::GetCachedDecorSize() void wxTopLevelWindowGTK::OnInternalIdle() { wxTopLevelWindowBase::OnInternalIdle(); - - // Synthetize activate events. - if ( g_sendActivateEvent != -1 ) - { - bool activate = g_sendActivateEvent != 0; - - // if (!activate) wxPrintf( wxT("de") ); - // wxPrintf( wxT("activate\n") ); - - // do it only once - g_sendActivateEvent = -1; - - wxTheApp->SetActive(activate, (wxWindow *)g_lastActiveFrame); - } } // ----------------------------------------------------------------------------