Fix generation of wxEVT_ACTIVATE_APP
Avoid spurious events when showing most native dialogs See #17260
This commit is contained in:
@@ -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()
|
bool wxApp::DoIdle()
|
||||||
{
|
{
|
||||||
guint id_save;
|
guint id_save;
|
||||||
@@ -123,6 +138,12 @@ bool wxApp::DoIdle()
|
|||||||
}
|
}
|
||||||
|
|
||||||
gdk_threads_enter();
|
gdk_threads_enter();
|
||||||
|
|
||||||
|
if (gs_focusChange) {
|
||||||
|
SetActive(gs_focusChange == 1, NULL);
|
||||||
|
gs_focusChange = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool needMore;
|
bool needMore;
|
||||||
do {
|
do {
|
||||||
ProcessPendingEvents();
|
ProcessPendingEvents();
|
||||||
@@ -415,8 +436,18 @@ bool wxApp::Initialize(int& argc_, wxChar **argv_)
|
|||||||
wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
|
wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// make sure GtkWidget type is loaded, idle hooks need it
|
// make sure GtkWidget type is loaded, signal emission hooks need it
|
||||||
g_type_class_ref(GTK_TYPE_WIDGET);
|
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();
|
WakeUpIdle();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -27,7 +27,6 @@
|
|||||||
#include "wx/frame.h"
|
#include "wx/frame.h"
|
||||||
#include "wx/icon.h"
|
#include "wx/icon.h"
|
||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
#include "wx/app.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/evtloop.h"
|
#include "wx/evtloop.h"
|
||||||
@@ -59,12 +58,6 @@ int wxOpenModalDialogsCount = 0;
|
|||||||
static wxTopLevelWindowGTK *g_activeFrame = NULL;
|
static wxTopLevelWindowGTK *g_activeFrame = NULL;
|
||||||
static wxTopLevelWindowGTK *g_lastActiveFrame = 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_globalCursor;
|
||||||
extern wxCursor g_busyCursor;
|
extern wxCursor g_busyCursor;
|
||||||
|
|
||||||
@@ -134,20 +127,6 @@ static gboolean gtk_frame_focus_in_callback( GtkWidget *widget,
|
|||||||
GdkEvent *WXUNUSED(event),
|
GdkEvent *WXUNUSED(event),
|
||||||
wxTopLevelWindowGTK *win )
|
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_activeFrame = win;
|
||||||
g_lastActiveFrame = g_activeFrame;
|
g_lastActiveFrame = g_activeFrame;
|
||||||
|
|
||||||
@@ -167,7 +146,6 @@ static gboolean gtk_frame_focus_in_callback( GtkWidget *widget,
|
|||||||
case -2: break;
|
case -2: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame);
|
|
||||||
wxActivateEvent event(wxEVT_ACTIVATE, true, g_activeFrame->GetId());
|
wxActivateEvent event(wxEVT_ACTIVATE, true, g_activeFrame->GetId());
|
||||||
event.SetEventObject(g_activeFrame);
|
event.SetEventObject(g_activeFrame);
|
||||||
g_activeFrame->HandleWindowEvent(event);
|
g_activeFrame->HandleWindowEvent(event);
|
||||||
@@ -186,18 +164,8 @@ gboolean gtk_frame_focus_out_callback(GtkWidget * WXUNUSED(widget),
|
|||||||
GdkEventFocus *WXUNUSED(gdk_event),
|
GdkEventFocus *WXUNUSED(gdk_event),
|
||||||
wxTopLevelWindowGTK * WXUNUSED(win))
|
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)
|
if (g_activeFrame)
|
||||||
{
|
{
|
||||||
wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), g_activeFrame);
|
|
||||||
wxActivateEvent event(wxEVT_ACTIVATE, false, g_activeFrame->GetId());
|
wxActivateEvent event(wxEVT_ACTIVATE, false, g_activeFrame->GetId());
|
||||||
event.SetEventObject(g_activeFrame);
|
event.SetEventObject(g_activeFrame);
|
||||||
g_activeFrame->HandleWindowEvent(event);
|
g_activeFrame->HandleWindowEvent(event);
|
||||||
@@ -1305,20 +1273,6 @@ wxTopLevelWindowGTK::DecorSize& wxTopLevelWindowGTK::GetCachedDecorSize()
|
|||||||
void wxTopLevelWindowGTK::OnInternalIdle()
|
void wxTopLevelWindowGTK::OnInternalIdle()
|
||||||
{
|
{
|
||||||
wxTopLevelWindowBase::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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user