#include "wx/defs.h"
+#include "wx/toplevel.h"
#include "wx/log.h"
#include "wx/dialog.h"
#include "wx/control.h"
// data
// ----------------------------------------------------------------------------
-extern wxList wxPendingDelete;
+extern wxList wxPendingDelete;
-extern int g_openDialogs;
-extern wxWindowGTK *g_delayedFocus;
+extern int g_openDialogs;
+extern wxWindowGTK *g_delayedFocus;
+
+// the frame that is currently active (i.e. its child has focus). It is
+// used to generate wxActivateEvents
+static wxTopLevelWindowGTK *g_activeFrame = (wxTopLevelWindowGTK*) NULL;
+static wxTopLevelWindowGTK *g_lastActiveFrame = (wxTopLevelWindowGTK*) 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;
+
+//-----------------------------------------------------------------------------
+// "focus_in_event"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static gint gtk_frame_focus_in_callback( GtkWidget *widget,
+ GdkEvent *WXUNUSED(event),
+ wxTopLevelWindowGTK *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ 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;
+
+ // wxPrintf( wxT("active: %s\n"), win->GetTitle().c_str() );
+
+ 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->GetEventHandler()->ProcessEvent(event);
+
+ return FALSE;
+}
+}
+
+//-----------------------------------------------------------------------------
+// "focus_out_event"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static gint gtk_frame_focus_out_callback( GtkWidget *widget,
+ GdkEventFocus *WXUNUSED(gdk_event),
+ wxTopLevelWindowGTK *win )
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ // if the focus goes out of our app alltogether, 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->GetEventHandler()->ProcessEvent(event);
+
+ g_activeFrame = NULL;
+ }
+
+ return FALSE;
+}
+}
//-----------------------------------------------------------------------------
// "focus" from m_window
//-----------------------------------------------------------------------------
+extern "C" {
static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
{
if (g_isIdle)
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
return TRUE;
}
+}
//-----------------------------------------------------------------------------
// "size_allocate"
//-----------------------------------------------------------------------------
+extern "C" {
static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxTopLevelWindowGTK *win )
{
if (g_isIdle)
win->GtkUpdateSize();
}
}
+}
//-----------------------------------------------------------------------------
// "delete_event"
//-----------------------------------------------------------------------------
+extern "C" {
static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win )
{
if (g_isIdle)
return TRUE;
}
+}
//-----------------------------------------------------------------------------
// "configure_event"
//-----------------------------------------------------------------------------
+extern "C" {
static gint
gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win )
{
if (!win->m_hasVMT || !win->IsShown())
return FALSE;
+
int x = 0;
int y = 0;
gdk_window_get_root_origin( win->m_widget->window, &x, &y );
return FALSE;
}
+}
//-----------------------------------------------------------------------------
// "realize" from m_widget
// we cannot MWM hints and icons before the widget has been realized,
// so we do this directly after realization
+extern "C" {
static void
gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget),
wxTopLevelWindowGTK *win )
win->SetIcons( iconsOld );
}
}
+}
//-----------------------------------------------------------------------------
// "map_event" from m_widget
//-----------------------------------------------------------------------------
+extern "C" {
static void
gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
GdkEvent * WXUNUSED(event),
{
win->SetIconizeState(FALSE);
}
+}
//-----------------------------------------------------------------------------
// "unmap_event" from m_widget
//-----------------------------------------------------------------------------
+extern "C" {
static void
gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
GdkEvent * WXUNUSED(event),
{
win->SetIconizeState(TRUE);
}
+}
//-----------------------------------------------------------------------------
// "expose_event" of m_client
//-----------------------------------------------------------------------------
+extern "C" {
static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
{
GtkPizza *pizza = GTK_PIZZA(widget);
return FALSE;
}
+}
//-----------------------------------------------------------------------------
// "draw" of m_client
#ifndef __WXGTK20__
+extern "C" {
static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
{
GtkPizza *pizza = GTK_PIZZA(widget);
(char *)"base",
0, 0, -1, -1);
}
+}
#endif // GTK+ 1.x
// e.g. in wxTaskBarIconAreaGTK
if (m_widget == NULL)
{
- GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
- if (style & wxFRAME_TOOL_WINDOW)
- win_type = GTK_WINDOW_POPUP;
-
if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
{
#ifdef __WXGTK20__
}
else
{
- m_widget = gtk_window_new(win_type);
+ m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+#if GTK_CHECK_VERSION(2,1,0)
+ if (style & wxFRAME_TOOL_WINDOW)
+ {
+ gtk_window_set_type_hint(GTK_WINDOW(m_widget),
+ GDK_WINDOW_TYPE_HINT_UTILITY);
+
+ // On some WMs, like KDE, a TOOL_WINDOW will still show
+ // on the taskbar, but on Gnome a TOOL_WINDOW will not.
+ // For consistency between WMs and with Windows, we
+ // should set the NO_TASKBAR flag which will apply
+ // the set_skip_taskbar_hint if it is available,
+ // ensuring no taskbar entry will appear.
+ style |= wxFRAME_NO_TASKBAR;
+ }
+#endif
+
}
}
- if (m_parent && (((GTK_IS_WINDOW(m_parent->m_widget)) &&
+ wxWindow *topParent = wxGetTopLevelParent(m_parent);
+ if (topParent && (((GTK_IS_WINDOW(topParent->m_widget)) &&
(GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) ||
(style & wxFRAME_FLOAT_ON_PARENT)))
{
- gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
+ gtk_window_set_transient_for( GTK_WINDOW(m_widget),
+ GTK_WINDOW(topParent->m_widget) );
}
#if GTK_CHECK_VERSION(2,2,0)
gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
+ // activation
+ gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
+ GTK_SIGNAL_FUNC(gtk_frame_focus_in_callback), (gpointer)this );
+ gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
+ GTK_SIGNAL_FUNC(gtk_frame_focus_out_callback), (gpointer)this );
+
// decorations
if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
{
{
gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
}
+
+ if (g_activeFrame == this)
+ g_activeFrame = NULL;
+ if (g_lastActiveFrame == this)
+ g_lastActiveFrame = NULL;
}
bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
{
- if (show == m_fsIsShowing) return FALSE; // return what?
+ if (show == m_fsIsShowing)
+ return FALSE; // return what?
m_fsIsShowing = show;
-
- GdkWindow *window = m_widget->window;
+
wxX11FullScreenMethod method =
wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(),
(WXWindow)GDK_ROOT_WINDOW());
- if (show)
+#if GTK_CHECK_VERSION(2,2,0)
+ // NB: gtk_window_fullscreen() uses freedesktop.org's WMspec extensions
+ // to switch to fullscreen, which is not always available. We must
+ // check if WM supports the spec and use legacy methods if it
+ // doesn't.
+ if (method == wxX11_FS_WMSPEC)
{
- m_fsSaveFlag = style;
- GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
- GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
-
- int screen_width,screen_height;
- wxDisplaySize( &screen_width, &screen_height );
-
- gint client_x, client_y, root_x, root_y;
- gint width, height;
-
- if (method != wxX11_FS_WMSPEC)
- {
- // don't do it always, Metacity hates it
- m_fsSaveGdkFunc = m_gdkFunc;
- m_fsSaveGdkDecor = m_gdkDecor;
- m_gdkFunc = m_gdkDecor = 0;
- gdk_window_set_decorations(window, (GdkWMDecoration)0);
- gdk_window_set_functions(window, (GdkWMFunction)0);
- }
-
- gdk_window_get_origin (m_widget->window, &root_x, &root_y);
- gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
- &width, &height, NULL);
-
- gdk_window_move_resize (m_widget->window, -client_x, -client_y,
- screen_width + 1, screen_height + 1);
+ if (show)
+ gtk_window_fullscreen( GTK_WINDOW( m_widget ) );
+ else
+ gtk_window_unfullscreen( GTK_WINDOW( m_widget ) );
- wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
- (WXWindow)GDK_ROOT_WINDOW(),
- (WXWindow)GDK_WINDOW_XWINDOW(window),
- show, &m_fsSaveFrame, method);
+ return TRUE;
}
else
+#endif // GTK+ >= 2.2.0
{
- if (method != wxX11_FS_WMSPEC)
+ GdkWindow *window = m_widget->window;
+
+ if (show)
{
- // don't do it always, Metacity hates it
- m_gdkFunc = m_fsSaveGdkFunc;
- m_gdkDecor = m_fsSaveGdkDecor;
- gdk_window_set_decorations(window, (GdkWMDecoration)m_gdkDecor);
- gdk_window_set_functions(window, (GdkWMFunction)m_gdkFunc);
+ m_fsSaveFlag = style;
+ GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
+ GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
+
+ int screen_width,screen_height;
+ wxDisplaySize( &screen_width, &screen_height );
+
+ gint client_x, client_y, root_x, root_y;
+ gint width, height;
+
+ if (method != wxX11_FS_WMSPEC)
+ {
+ // don't do it always, Metacity hates it
+ m_fsSaveGdkFunc = m_gdkFunc;
+ m_fsSaveGdkDecor = m_gdkDecor;
+ m_gdkFunc = m_gdkDecor = 0;
+ gdk_window_set_decorations(window, (GdkWMDecoration)0);
+ gdk_window_set_functions(window, (GdkWMFunction)0);
+ }
+
+ gdk_window_get_origin (m_widget->window, &root_x, &root_y);
+ gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
+ &width, &height, NULL);
+
+ gdk_window_move_resize (m_widget->window, -client_x, -client_y,
+ screen_width + 1, screen_height + 1);
+
+ wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
+ (WXWindow)GDK_ROOT_WINDOW(),
+ (WXWindow)GDK_WINDOW_XWINDOW(window),
+ show, &m_fsSaveFrame, method);
+ }
+ else
+ {
+ if (method != wxX11_FS_WMSPEC)
+ {
+ // don't do it always, Metacity hates it
+ m_gdkFunc = m_fsSaveGdkFunc;
+ m_gdkDecor = m_fsSaveGdkDecor;
+ gdk_window_set_decorations(window, (GdkWMDecoration)m_gdkDecor);
+ gdk_window_set_functions(window, (GdkWMFunction)m_gdkFunc);
+ }
+
+ wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
+ (WXWindow)GDK_ROOT_WINDOW(),
+ (WXWindow)GDK_WINDOW_XWINDOW(window),
+ show, &m_fsSaveFrame, method);
+
+ SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y,
+ m_fsSaveFrame.width, m_fsSaveFrame.height);
}
-
- wxSetFullScreenStateX11((WXDisplay*)GDK_DISPLAY(),
- (WXWindow)GDK_ROOT_WINDOW(),
- (WXWindow)GDK_WINDOW_XWINDOW(window),
- show, &m_fsSaveFrame, method);
-
- SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y,
- m_fsSaveFrame.width, m_fsSaveFrame.height);
}
-
return TRUE;
}
GtkOnSize( m_x, m_y, m_width, m_height );
}
-
+
+ if (show)
+ gtk_widget_set_uposition( m_widget, m_x, m_y );
+
return wxWindow::Show( show );
}
+void wxTopLevelWindowGTK::Raise()
+{
+#ifdef __WXGTK20__
+ gtk_window_present( GTK_WINDOW( m_widget ) );
+#else
+ wxWindow::Raise();
+#endif
+}
+
void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
{
wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
}
wxWindow::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);
+ }
}
// ----------------------------------------------------------------------------
bool wxTopLevelWindowGTK::IsActive()
{
-#ifdef __WXGTK20__
- // Order the conditions like this so we don't
- // have to decide how to include version for GTK+ 1 versus 2
-#if GTK_CHECK_VERSION(2,2,0)
- return GTK_WINDOW( m_widget )->has_toplevel_focus;
-#else
- return wxTopLevelWindowBase::IsActive();
-#endif
-#else
- return wxTopLevelWindowBase::IsActive();
-#endif
+ return (this == (wxTopLevelWindowGTK*)g_activeFrame);
}