X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/83afe21166ad23a402185eef5dd47782597e8f91..222702b112dcc7bebe018d6f4d66fe469fefd02c:/src/gtk/toplevel.cpp?ds=sidebyside diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index f2005c8c5d..c8705377dc 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -15,21 +15,28 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "toplevel.h" #endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + #ifdef __VMS #define XIconifyWindow XICONIFYWINDOW #endif #include "wx/defs.h" +#include "wx/toplevel.h" +#include "wx/log.h" #include "wx/dialog.h" #include "wx/control.h" #include "wx/app.h" #include "wx/dcclient.h" #include "wx/gtk/private.h" +#include "wx/timer.h" +#include "wx/settings.h" #include #include @@ -55,15 +62,102 @@ extern bool g_isIdle; // data // ---------------------------------------------------------------------------- -extern wxList wxPendingDelete; +extern wxList wxPendingDelete; + +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(); -extern int g_openDialogs; -extern wxWindowGTK *g_delayedFocus; + // 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) @@ -73,11 +167,13 @@ static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUS 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) @@ -100,15 +196,16 @@ static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* win->m_width = alloc->width; win->m_height = alloc->height; - win->m_queuedFullRedraw = TRUE; win->GtkUpdateSize(); } } +} //----------------------------------------------------------------------------- // "delete_event" //----------------------------------------------------------------------------- +extern "C" { static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win ) { if (g_isIdle) @@ -121,12 +218,14 @@ static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WX return TRUE; } +} //----------------------------------------------------------------------------- // "configure_event" //----------------------------------------------------------------------------- +extern "C" { static gint gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win ) { @@ -136,6 +235,7 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WX 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 ); @@ -148,6 +248,7 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WX return FALSE; } +} //----------------------------------------------------------------------------- // "realize" from m_widget @@ -156,6 +257,7 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WX // 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 ) @@ -184,11 +286,13 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), win->SetIcons( iconsOld ); } } +} //----------------------------------------------------------------------------- // "map_event" from m_widget //----------------------------------------------------------------------------- +extern "C" { static void gtk_frame_map_callback( GtkWidget * WXUNUSED(widget), GdkEvent * WXUNUSED(event), @@ -196,11 +300,13 @@ gtk_frame_map_callback( GtkWidget * WXUNUSED(widget), { win->SetIconizeState(FALSE); } +} //----------------------------------------------------------------------------- // "unmap_event" from m_widget //----------------------------------------------------------------------------- +extern "C" { static void gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget), GdkEvent * WXUNUSED(event), @@ -208,11 +314,13 @@ gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget), { 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); @@ -225,7 +333,8 @@ static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_ev (char *)"base", 0, 0, -1, -1); - return TRUE; + return FALSE; +} } //----------------------------------------------------------------------------- @@ -234,6 +343,7 @@ static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_ev #ifndef __WXGTK20__ +extern "C" { static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win ) { GtkPizza *pizza = GTK_PIZZA(widget); @@ -246,6 +356,7 @@ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxW (char *)"base", 0, 0, -1, -1); } +} #endif // GTK+ 1.x @@ -259,7 +370,7 @@ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxW /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because * C++ has no virtual methods in a constructor. We have to emulate a - * virtual function here as wxWindows requires different ways to insert + * virtual function here as wxWidgets requires different ways to insert * a child in container classes. */ static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child ) @@ -321,14 +432,8 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, // always create a frame of some reasonable, even if arbitrary, size (at // least for MSW compatibility) wxSize size = sizeOrig; - if ( size.x == -1 || size.y == -1 ) - { - wxSize sizeDpy = wxGetDisplaySize(); - if ( size.x == -1 ) - size.x = sizeDpy.x / 3; - if ( size.y == -1 ) - size.y = sizeDpy.y / 5; - } + size.x = WidthDefault(size.x); + size.y = HeightDefault(size.y); wxTopLevelWindows.Append( this ); @@ -345,28 +450,76 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow; - GtkWindowType win_type = GTK_WINDOW_TOPLEVEL; - - if (style & wxFRAME_TOOL_WINDOW) - win_type = GTK_WINDOW_POPUP; - - if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) + // NB: m_widget may be !=NULL if it was created by derived class' Create, + // e.g. in wxTaskBarIconAreaGTK + if (m_widget == NULL) { - // there is no more GTK_WINDOW_DIALOG in 2.0 + if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) + { #ifdef __WXGTK20__ - win_type = GTK_WINDOW_TOPLEVEL; + m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); + // Tell WM that this is a dialog window and make it center + // on parent by default (this is what GtkDialog ctor does): + gtk_window_set_type_hint(GTK_WINDOW(m_widget), + GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_window_set_position(GTK_WINDOW(m_widget), + GTK_WIN_POS_CENTER_ON_PARENT); #else - win_type = GTK_WINDOW_DIALOG; + m_widget = gtk_window_new(GTK_WINDOW_DIALOG); #endif + } + else + { + m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); +#if GTK_CHECK_VERSION(2,1,0) + 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 + } } - m_widget = gtk_window_new( win_type ); + 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(topParent->m_widget) ); + } - if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)) && - (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)) +#if GTK_CHECK_VERSION(2,2,0) + if (!gtk_check_version(2,2,0)) { - gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) ); + if (style & wxFRAME_NO_TASKBAR) + { + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget), TRUE); + } + } +#endif + +#if GTK_CHECK_VERSION(2,4,0) + if (!gtk_check_version(2,4,0)) + { + if (style & wxSTAY_ON_TOP) + { + gtk_window_set_keep_above(GTK_WINDOW(m_widget), TRUE); + } } +#endif if (!name.IsEmpty()) gtk_window_set_wmclass( GTK_WINDOW(m_widget), wxGTK_CONV( name ), wxGTK_CONV( name ) ); @@ -383,13 +536,16 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS ); gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget ); - // for m_mainWidget themes - gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event", + if (m_miniEdge == 0) // wxMiniFrame has its own version. + { + // For m_mainWidget themes + gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event", GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this ); #ifndef __WXGTK20__ - gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw", + gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw", GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this ); #endif + } // m_wxwindow only represents the client area without toolbar and menubar m_wxwindow = gtk_pizza_new(); @@ -436,6 +592,12 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, 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)) { @@ -450,10 +612,15 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, // All this is for Motif Window Manager "hints" and is supposed to be // recognized by other WMs as well. if ((style & wxCAPTION) != 0) + { m_gdkDecor |= GDK_DECOR_TITLE; - if ((style & wxSYSTEM_MENU) != 0) + } + if ((style & wxCLOSE_BOX) != 0) { m_gdkFunc |= GDK_FUNC_CLOSE; + } + if ((style & wxSYSTEM_MENU) != 0) + { m_gdkDecor |= GDK_DECOR_MENU; } if ((style & wxMINIMIZE_BOX) != 0) @@ -483,7 +650,7 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK() wxASSERT_MSG( FALSE, _T("Window still grabbed")); RemoveGrab(); } - + m_isBeingDeleted = TRUE; // it may also be GtkScrolledWindow in the case of an MDI child @@ -491,107 +658,98 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK() { gtk_window_set_focus( GTK_WINDOW(m_widget), NULL ); } - - wxTopLevelWindows.DeleteObject( this ); - - if (wxTheApp->GetTopWindow() == this) - wxTheApp->SetTopWindow( (wxWindow*) NULL ); - - if ((wxTopLevelWindows.Number() == 0) && - (wxTheApp->GetExitOnFrameDelete())) - { - wxTheApp->ExitMainLoop(); - } + + if (g_activeFrame == this) + g_activeFrame = NULL; + if (g_lastActiveFrame == this) + g_lastActiveFrame = NULL; } -// X11 ICCCM values for window layers -#define WIN_LAYER_NORMAL 4 -#define WIN_LAYER_ABOVE_DOCK 10 - -// X11 window manager property name -#define XA_WIN_LAYER "_WIN_LAYER" - -// X11 window manager property name atom -static Atom gs_XA_WIN_LAYER = 0; - - -static void wx_win_hints_set_layer(GtkWidget *window, int layer) -{ -#ifndef __WXGTK20__ - XEvent xev; - GdkWindowPrivate *priv; - gint prev_error; - - prev_error = gdk_error_warnings; - gdk_error_warnings = 0; - priv = (GdkWindowPrivate*)(GTK_WIDGET(window)->window); - - if (GTK_WIDGET_MAPPED(window)) - { - xev.type = ClientMessage; - xev.xclient.type = ClientMessage; - xev.xclient.window = priv->xwindow; - xev.xclient.message_type = gs_XA_WIN_LAYER; - xev.xclient.format = 32; - xev.xclient.data.l[0] = (long)layer; - xev.xclient.data.l[1] = gdk_time_get(); - - XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), False, - SubstructureNotifyMask, (XEvent*) &xev); - } - else - { - long data[1]; - - data[0] = layer; - XChangeProperty(GDK_DISPLAY(), priv->xwindow, gs_XA_WIN_LAYER, - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); - } - gdk_error_warnings = prev_error; -#endif -} bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style ) { - if (show == m_fsIsShowing) return FALSE; // return what? - - if (gs_XA_WIN_LAYER == 0) - { - // Initialose X11 Atom only once - gs_XA_WIN_LAYER = XInternAtom( GDK_DISPLAY(), XA_WIN_LAYER, False ); - } + if (show == m_fsIsShowing) + return FALSE; // return what? m_fsIsShowing = show; - - if (show) + + wxX11FullScreenMethod method = + wxGetFullScreenMethodX11((WXDisplay*)GDK_DISPLAY(), + (WXWindow)GDK_ROOT_WINDOW()); + +#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_fsSaveGdkFunc = m_gdkFunc; - m_fsSaveGdkDecor = m_gdkDecor; - 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; - - 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); - - wx_win_hints_set_layer( m_widget, WIN_LAYER_ABOVE_DOCK ); + if (show) + gtk_window_fullscreen( GTK_WINDOW( m_widget ) ); + else + gtk_window_unfullscreen( GTK_WINDOW( m_widget ) ); - gdk_window_move_resize (m_widget->window, -client_x, -client_y, - screen_width + 1, screen_height + 1); + return TRUE; } else +#endif // GTK+ >= 2.2.0 { - wx_win_hints_set_layer( m_widget, WIN_LAYER_NORMAL ); - - SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height ); + GdkWindow *window = m_widget->window; + + if (show) + { + 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); + } } return TRUE; @@ -614,10 +772,22 @@ bool wxTopLevelWindowGTK::Show( bool show ) 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") ); @@ -671,6 +841,16 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si maxWidth = GetMaxWidth(), maxHeight = GetMaxHeight(); +#ifdef __WXGPE__ + // GPE's window manager doesn't like size hints + // at all, esp. when the user has to use the + // virtual keyboard. + minWidth = -1; + minHeight = -1; + maxWidth = -1; + maxHeight = -1; +#endif + if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth; if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight; if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth; @@ -752,6 +932,16 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), maxWidth = GetMaxWidth(), maxHeight = GetMaxHeight(); +#ifdef __WXGPE__ + // GPE's window manager doesn't like size hints + // at all, esp. when the user has to use the + // virtual keyboard. + minWidth = -1; + minHeight = -1; + maxWidth = -1; + maxHeight = -1; +#endif + if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth; if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight; if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth; @@ -778,7 +968,7 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), // Gtk-WARNING **: gtk_widget_size_allocate(): // attempt to allocate widget with width 65535 and height 600 // but I don't have time to track them all now.. - // + // // Really we need to encapulate all this height/width business and // stop any old method from ripping at the members directly and // scattering -1's without regard for who might resolve them later. @@ -845,12 +1035,31 @@ void wxTopLevelWindowGTK::OnInternalIdle() if ( g_delayedFocus && wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this ) { + wxLogTrace(_T("focus"), + _T("Setting focus from wxTLW::OnIdle() to %s(%s)"), + g_delayedFocus->GetClassInfo()->GetClassName(), + g_delayedFocus->GetLabel().c_str()); + g_delayedFocus->SetFocus(); g_delayedFocus = NULL; } } 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); + } } // ---------------------------------------------------------------------------- @@ -865,21 +1074,6 @@ void wxTopLevelWindowGTK::SetTitle( const wxString &title ) gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) ); } -void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon ) -{ - if ( !icon.Ok() ) - return; - - if (!m_widget->window) - return; - - wxMask *mask = icon.GetMask(); - GdkBitmap *bm = (GdkBitmap *) NULL; - if (mask) bm = mask->GetBitmap(); - - gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm ); -} - void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon ) { SetIcons( wxIconBundle( icon ) ); @@ -888,42 +1082,92 @@ void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon ) void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons ) { wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); - GdkWindow* window = m_widget->window; wxTopLevelWindowBase::SetIcons( icons ); - DoSetIcon( icons.GetIcon( -1 ) ); - if ( window ) +#ifdef __WXGTK20__ + GList *list = NULL; + size_t max = icons.m_icons.GetCount(); + + for (size_t i = 0; i < max; i++) { - wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ), - (WXWindow)GDK_WINDOW_XWINDOW( window ), icons ); + if (icons.m_icons[i].Ok()) + { + list = g_list_prepend(list, icons.m_icons[i].GetPixbuf()); + } } + gtk_window_set_icon_list(GTK_WINDOW(m_widget), list); + g_list_free(list); + +#else // !__WXGTK20__ + GdkWindow* window = m_widget->window; + if (!window) + return; + + wxIcon icon = icons.GetIcon(-1); + if (icon.Ok()) + { + wxMask *mask = icon.GetMask(); + GdkBitmap *bm = (GdkBitmap *) NULL; + if (mask) bm = mask->GetBitmap(); + + gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm ); + } + + wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ), + (WXWindow)GDK_WINDOW_XWINDOW( window ), icons ); +#endif // !__WXGTK20__ } // ---------------------------------------------------------------------------- // frame state: maximized/iconized/normal // ---------------------------------------------------------------------------- -void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize)) +void wxTopLevelWindowGTK::Maximize(bool maximize) { +#ifdef __WXGTK20__ + if (maximize) + gtk_window_maximize( GTK_WINDOW( m_widget ) ); + else + gtk_window_unmaximize( GTK_WINDOW( m_widget ) ); +#else wxFAIL_MSG( _T("not implemented") ); +#endif } bool wxTopLevelWindowGTK::IsMaximized() const { +#ifdef __WXGTK20__ + if(!m_widget->window) + return false; + + return gdk_window_get_state(m_widget->window) & GDK_WINDOW_STATE_MAXIMIZED; +#else // wxFAIL_MSG( _T("not implemented") ); // This is an approximation return FALSE; +#endif } void wxTopLevelWindowGTK::Restore() { +#ifdef __WXGTK20__ + // "Present" seems similar enough to "restore" + gtk_window_present( GTK_WINDOW( m_widget ) ); +#else wxFAIL_MSG( _T("not implemented") ); +#endif } void wxTopLevelWindowGTK::Iconize( bool iconize ) { +#ifdef __WXGTK20__ + if (iconize) + gtk_window_iconify( GTK_WINDOW( m_widget ) ); + else + gtk_window_deiconify( GTK_WINDOW( m_widget ) ); +#else if (iconize) { GdkWindow *window = m_widget->window; @@ -935,6 +1179,7 @@ void wxTopLevelWindowGTK::Iconize( bool iconize ) GDK_WINDOW_XWINDOW( window ), DefaultScreen( GDK_DISPLAY() ) ); } +#endif } bool wxTopLevelWindowGTK::IsIconized() const @@ -971,4 +1216,50 @@ void wxTopLevelWindowGTK::RemoveGrab() } } -// vi:sts=4:sw=4:et + +// helper +static bool do_shape_combine_region(GdkWindow* window, const wxRegion& region) +{ + if (window) + { + if (region.IsEmpty()) + { + gdk_window_shape_combine_mask(window, NULL, 0, 0); + } + else + { +#ifdef __WXGTK20__ + gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0); +#else + wxBitmap bmp = region.ConvertToBitmap(); + bmp.SetMask(new wxMask(bmp, *wxBLACK)); + GdkBitmap* mask = bmp.GetMask()->GetBitmap(); + gdk_window_shape_combine_mask(window, mask, 0, 0); +#endif + return TRUE; + } + } + return FALSE; +} + + +bool wxTopLevelWindowGTK::SetShape(const wxRegion& region) +{ + wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), FALSE, + _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); + + GdkWindow *window = NULL; + if (m_wxwindow) + { + window = GTK_PIZZA(m_wxwindow)->bin_window; + do_shape_combine_region(window, region); + } + window = m_widget->window; + return do_shape_combine_region(window, region); +} + +bool wxTopLevelWindowGTK::IsActive() +{ + return (this == (wxTopLevelWindowGTK*)g_activeFrame); +} +