X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0a164d4c4e75bd48f6a0a484fb267b0dc337c541..4837b89e3b9ddc02a752d9937e3e1d9f92328851:/src/gtk/toplevel.cpp diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index 312f2ce56d..d50dd65fcf 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -15,10 +15,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "toplevel.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -79,6 +75,46 @@ static wxTopLevelWindowGTK *g_lastActiveFrame = (wxTopLevelWindowGTK*) NULL; // send any activate events at all static int g_sendActivateEvent = -1; +//----------------------------------------------------------------------------- +// RequestUserAttention related functions +//----------------------------------------------------------------------------- + +extern "C" { +static void wxgtk_window_set_urgency_hint (GtkWindow *win, + gboolean setting) +{ + wxASSERT_MSG( GTK_WIDGET_REALIZED(win), wxT("wxgtk_window_set_urgency_hint: GdkWindow not realized") ); + GdkWindow *window = GTK_WIDGET(win)->window; + XWMHints *wm_hints; + + wm_hints = XGetWMHints(GDK_WINDOW_XDISPLAY(window), GDK_WINDOW_XWINDOW(window)); + + if (!wm_hints) + wm_hints = XAllocWMHints(); + + if (setting) + wm_hints->flags |= XUrgencyHint; + else + wm_hints->flags &= ~XUrgencyHint; + + XSetWMHints(GDK_WINDOW_XDISPLAY(window), GDK_WINDOW_XWINDOW(window), wm_hints); + XFree(wm_hints); +} + +static gint gtk_frame_urgency_timer_callback( wxTopLevelWindowGTK *win ) +{ +#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0) + if(!gtk_check_version(2,7,0)) + gtk_window_set_urgency_hint(GTK_WINDOW( win->m_widget ), FALSE); + else +#endif + wxgtk_window_set_urgency_hint(GTK_WINDOW( win->m_widget ), FALSE); + + win->m_urgency_hint = -2; + return FALSE; +} +} + //----------------------------------------------------------------------------- // "focus_in_event" //----------------------------------------------------------------------------- @@ -110,6 +146,28 @@ static gint gtk_frame_focus_in_callback( GtkWidget *widget, // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() ); + // MR: wxRequestUserAttention related block + switch( win->m_urgency_hint ) + { + default: + gtk_timeout_remove( win->m_urgency_hint ); + // no break, fallthrough to remove hint too + case -1: +#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0) + if(!gtk_check_version(2,7,0)) + gtk_window_set_urgency_hint(GTK_WINDOW( widget ), FALSE); + else +#endif + { + wxgtk_window_set_urgency_hint(GTK_WINDOW( widget ), FALSE); + } + + win->m_urgency_hint = -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()); event.SetEventObject(g_activeFrame); @@ -420,6 +478,8 @@ void wxTopLevelWindowGTK::Init() m_themeEnabled = true; m_gdkDecor = m_gdkFunc = 0; m_grabbed = false; + + m_urgency_hint = -2; } bool wxTopLevelWindowGTK::Create( wxWindow *parent, @@ -575,10 +635,6 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, gtk_signal_connect( GTK_OBJECT(m_widget), "realize", GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this ); - // the only way to get the window size is to connect to this event - gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event", - GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this ); - // map and unmap for iconized state gtk_signal_connect( GTK_OBJECT(m_widget), "map_event", GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this ); @@ -690,8 +746,6 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style ) gtk_window_fullscreen( GTK_WINDOW( m_widget ) ); else gtk_window_unfullscreen( GTK_WINDOW( m_widget ) ); - - return true; } else #endif // GTK+ >= 2.2.0 @@ -732,7 +786,7 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style ) (WXWindow)GDK_WINDOW_XWINDOW(window), show, &m_fsSaveFrame, method); } - else + else // hide { if (method != wxX11_FS_WMSPEC) { @@ -753,6 +807,11 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style ) } } + // documented behaviour is to show the window if it's still hidden when + // showing it full screen + if ( show && !IsShown() ) + Show(); + return true; } @@ -1263,3 +1322,38 @@ bool wxTopLevelWindowGTK::IsActive() { return (this == (wxTopLevelWindowGTK*)g_activeFrame); } + +void wxTopLevelWindowGTK::RequestUserAttention(int flags) +{ + bool new_hint_value = false; + + // FIXME: This is a workaround to focus handling problem + // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't + // yet been processed, and the internal focus system is not up to date yet. + // wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR + ::wxYieldIfNeeded(); + + if(m_urgency_hint >= 0) + gtk_timeout_remove(m_urgency_hint); + + m_urgency_hint = -2; + + if( GTK_WIDGET_REALIZED(m_widget) && !IsActive() ) + { + new_hint_value = true; + + if (flags & wxUSER_ATTENTION_INFO) + { + m_urgency_hint = gtk_timeout_add(5000, (GtkFunction)gtk_frame_urgency_timer_callback, this); + } else { + m_urgency_hint = -1; + } + } + +#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,7,0) + if(!gtk_check_version(2,7,0)) + gtk_window_set_urgency_hint(GTK_WINDOW( m_widget ), new_hint_value); + else +#endif + wxgtk_window_set_urgency_hint(GTK_WINDOW( m_widget ), new_hint_value); +}