X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7d9f12f3b9f997b6308faf336d5381be591b71f4..9345ca55cb85bbc82d4122422562047e5a02ad3d:/src/gtk1/toplevel.cpp diff --git a/src/gtk1/toplevel.cpp b/src/gtk1/toplevel.cpp index 5e5af4d54f..9660e9d30e 100644 --- a/src/gtk1/toplevel.cpp +++ b/src/gtk1/toplevel.cpp @@ -15,20 +15,26 @@ // 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/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 #include @@ -38,45 +44,26 @@ #include "wx/gtk/win_gtk.h" +#include "wx/unix/utilsx11.h" + +// XA_CARDINAL +#include + // ---------------------------------------------------------------------------- // idle system // ---------------------------------------------------------------------------- extern void wxapp_install_idle_handler(); extern bool g_isIdle; -extern int g_openDialogs; - -// ---------------------------------------------------------------------------- -// event tables -// ---------------------------------------------------------------------------- - -#ifndef __WXUNIVERSAL__ - IMPLEMENT_DYNAMIC_CLASS(wxTopLevelWindow, wxWindow) -#endif // ---------------------------------------------------------------------------- // data // ---------------------------------------------------------------------------- -extern wxList wxPendingDelete; - -// ---------------------------------------------------------------------------- -// debug -// ---------------------------------------------------------------------------- +extern wxList wxPendingDelete; -#ifdef __WXDEBUG__ - -extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ); - -#endif - -// ============================================================================ -// implementation -// ============================================================================ - -// ---------------------------------------------------------------------------- -// GTK callbacks -// ---------------------------------------------------------------------------- +extern int g_openDialogs; +extern wxWindowGTK *g_delayedFocus; //----------------------------------------------------------------------------- // "focus" from m_window @@ -133,7 +120,8 @@ static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WX wxapp_install_idle_handler(); if (win->IsEnabled() && - (g_openDialogs == 0 || (win->GetExtraStyle() & wxTLW_EX_DIALOG))) + (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) || + win->IsGrabbed())) win->Close(); return TRUE; @@ -145,28 +133,19 @@ static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WX //----------------------------------------------------------------------------- static gint -#if (GTK_MINOR_VERSION > 0) gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win ) -#else -gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxTopLevelWindowGTK *win ) -#endif { if (g_isIdle) wxapp_install_idle_handler(); - if (!win->m_hasVMT) + if (!win->m_hasVMT || !win->IsShown()) return FALSE; -#if (GTK_MINOR_VERSION > 0) int x = 0; int y = 0; gdk_window_get_root_origin( win->m_widget->window, &x, &y ); win->m_x = x; win->m_y = y; -#else - win->m_x = event->x; - win->m_y = event->y; -#endif wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() ); mevent.SetEventObject( win ); @@ -179,83 +158,35 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *ev // "realize" from m_widget //----------------------------------------------------------------------------- -/* we cannot MWM hints and icons before the widget has been realized, - so we do this directly after realization */ +// we cannot MWM hints and icons before the widget has been realized, +// so we do this directly after realization static void -gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win ) +gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), + wxTopLevelWindowGTK *win ) { if (g_isIdle) wxapp_install_idle_handler(); - if ((win->m_miniEdge > 0) || (win->HasFlag(wxSIMPLE_BORDER)) || (win->HasFlag(wxNO_BORDER))) - { - /* This is a mini-frame or a borderless frame. */ - gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)0 ); - gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)0 ); - } - else - { - /* All this is for Motif Window Manager "hints" and is supposed to be - recognized by other WM as well. Not tested. */ - long decor = (long) GDK_DECOR_BORDER; - long func = (long) GDK_FUNC_MOVE; - - if ((win->GetWindowStyle() & wxCAPTION) != 0) - decor |= GDK_DECOR_TITLE; - if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0) - { - decor |= GDK_DECOR_MENU; - func |= GDK_FUNC_CLOSE; - } - if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0) - { - func |= GDK_FUNC_MINIMIZE; - decor |= GDK_DECOR_MINIMIZE; - } - if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0) - { - func |= GDK_FUNC_MAXIMIZE; - decor |= GDK_DECOR_MAXIMIZE; - } - if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0) - { - func |= GDK_FUNC_RESIZE; - decor |= GDK_DECOR_RESIZEH; - } - - gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor); - gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func); - } + // All this is for Motif Window Manager "hints" and is supposed to be + // recognized by other WM as well. Not tested. + gdk_window_set_decorations(win->m_widget->window, + (GdkWMDecoration)win->m_gdkDecor); + gdk_window_set_functions(win->m_widget->window, + (GdkWMFunction)win->m_gdkFunc); - /* GTK's shrinking/growing policy */ - if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0) + // GTK's shrinking/growing policy + if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0) gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1); else gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1); - /* reset the icon */ - wxIcon iconOld = win->GetIcon(); - if ( iconOld != wxNullIcon ) + // reset the icon + wxIconBundle iconsOld = win->GetIcons(); + if ( iconsOld.GetIcon(-1).Ok() ) { - wxIcon icon( iconOld ); win->SetIcon( wxNullIcon ); - win->SetIcon( icon ); - } - - /* we set the focus to the child that accepts the focus. this - doesn't really have to be done in "realize" but why not? */ - wxWindowList::Node *node = win->GetChildren().GetFirst(); - while (node) - { - wxWindow *child = node->GetData(); - if (child->AcceptsFocus()) - { - child->SetFocus(); - break; - } - - node = node->GetNext(); + win->SetIcons( iconsOld ); } } @@ -291,25 +222,38 @@ static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_ev { GtkPizza *pizza = GTK_PIZZA(widget); - gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL, - GTK_SHADOW_NONE, &gdk_event->area, win->m_widget, "base", 0, 0, -1, -1); + gtk_paint_flat_box (win->m_widget->style, + pizza->bin_window, GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + &gdk_event->area, + win->m_widget, + (char *)"base", + 0, 0, -1, -1); - return TRUE; + return FALSE; } //----------------------------------------------------------------------------- // "draw" of m_client //----------------------------------------------------------------------------- +#ifndef __WXGTK20__ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win ) { GtkPizza *pizza = GTK_PIZZA(widget); - gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL, - GTK_SHADOW_NONE, rect, win->m_widget, "base", 0, 0, -1, -1); + gtk_paint_flat_box (win->m_widget->style, + pizza->bin_window, GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + rect, + win->m_widget, + (char *)"base", + 0, 0, -1, -1); } +#endif // GTK+ 1.x + // ---------------------------------------------------------------------------- // wxTopLevelWindowGTK itself // ---------------------------------------------------------------------------- @@ -329,7 +273,7 @@ static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow if (!parent->m_insertInClientArea) { - /* these are outside the client area */ + // these are outside the client area wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent; gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget), GTK_WIDGET(child->m_widget), @@ -340,7 +284,7 @@ static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow } else { - /* these are inside the client area */ + // these are inside the client area gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow), GTK_WIDGET(child->m_widget), child->m_x, @@ -349,7 +293,7 @@ static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow child->m_height ); } - /* resize on OnInternalIdle */ + // resize on OnInternalIdle parent->GtkUpdateSize(); } @@ -364,19 +308,20 @@ void wxTopLevelWindowGTK::Init() m_miniTitle = 0; m_mainWidget = (GtkWidget*) NULL; m_insertInClientArea = TRUE; - m_isFrame = TRUE; m_isIconized = FALSE; m_fsIsShowing = FALSE; m_themeEnabled = TRUE; + m_gdkDecor = m_gdkFunc = 0; + m_grabbed = FALSE; } bool wxTopLevelWindowGTK::Create( wxWindow *parent, - wxWindowID id, - const wxString& title, - const wxPoint& pos, - const wxSize& sizeOrig, - long style, - const wxString &name ) + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& sizeOrig, + long style, + const wxString &name ) { // always create a frame of some reasonable, even if arbitrary, size (at // least for MSW compatibility) @@ -409,60 +354,64 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, if (style & wxFRAME_TOOL_WINDOW) win_type = GTK_WINDOW_POPUP; - - if (GetExtraStyle() & wxTLW_EX_DIALOG) + + if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) + { + // there is no more GTK_WINDOW_DIALOG in 2.0 +#ifdef __WXGTK20__ + win_type = GTK_WINDOW_TOPLEVEL; +#else win_type = GTK_WINDOW_DIALOG; +#endif + } m_widget = gtk_window_new( win_type ); - if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget))) + if (m_parent && (((GTK_IS_WINDOW(m_parent->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) ); + } if (!name.IsEmpty()) - gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() ); - -#ifdef __WXDEBUG__ - debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name ); -#endif + gtk_window_set_wmclass( GTK_WINDOW(m_widget), wxGTK_CONV( name ), wxGTK_CONV( name ) ); - gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() ); + gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) ); GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event", GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this ); - /* m_mainWidget holds the toolbar, the menubar and the client area */ + // m_mainWidget holds the toolbar, the menubar and the client area m_mainWidget = gtk_pizza_new(); gtk_widget_show( m_mainWidget ); 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 ); - gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw", +#ifndef __WXGTK20__ + gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw", GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this ); - -#ifdef __WXDEBUG__ - debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name ); #endif + } - /* m_wxwindow only represents the client area without toolbar and menubar */ + // m_wxwindow only represents the client area without toolbar and menubar m_wxwindow = gtk_pizza_new(); gtk_widget_show( m_wxwindow ); gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow ); -#ifdef __WXDEBUG__ - debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name ); -#endif - - /* we donm't allow the frame to get the focus as otherwise - the frame will grab it at arbitrary focus changes. */ + // we donm't allow the frame to get the focus as otherwise + // the frame will grab it at arbitrary focus changes GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); if (m_parent) m_parent->AddChild( this ); - /* the user resized the frame by dragging etc. */ + // the user resized the frame by dragging etc. gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate", GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this ); @@ -470,89 +419,162 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, if ((m_x != -1) || (m_y != -1)) gtk_widget_set_uposition( m_widget, m_x, m_y ); - gtk_widget_set_usize( m_widget, m_width, m_height ); - /* we cannot set MWM hints and icons before the widget has - been realized, so we do this directly after realization */ + gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height ); + + // we cannot set MWM hints and icons before the widget has + // been realized, so we do this directly after realization 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 */ + // 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 */ + // map and unmap for iconized state gtk_signal_connect( GTK_OBJECT(m_widget), "map_event", GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this ); gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event", GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this ); - /* the only way to get the window size is to connect to this event */ + // 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 ); - /* disable native tab traversal */ + // disable native tab traversal gtk_signal_connect( GTK_OBJECT(m_widget), "focus", GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this ); + // decorations + if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER)) + { + m_gdkDecor = 0; + m_gdkFunc = 0; + } + else + { + m_gdkDecor = (long) GDK_DECOR_BORDER; + m_gdkFunc = (long) GDK_FUNC_MOVE; + + // 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 & wxCLOSE_BOX) != 0) + { + m_gdkFunc |= GDK_FUNC_CLOSE; + } + if ((style & wxSYSTEM_MENU) != 0) + { + m_gdkDecor |= GDK_DECOR_MENU; + } + if ((style & wxMINIMIZE_BOX) != 0) + { + m_gdkFunc |= GDK_FUNC_MINIMIZE; + m_gdkDecor |= GDK_DECOR_MINIMIZE; + } + if ((style & wxMAXIMIZE_BOX) != 0) + { + m_gdkFunc |= GDK_FUNC_MAXIMIZE; + m_gdkDecor |= GDK_DECOR_MAXIMIZE; + } + if ((style & wxRESIZE_BORDER) != 0) + { + m_gdkFunc |= GDK_FUNC_RESIZE; + m_gdkDecor |= GDK_DECOR_RESIZEH; + } + } + return TRUE; } wxTopLevelWindowGTK::~wxTopLevelWindowGTK() { - m_isBeingDeleted = TRUE; - - wxTopLevelWindows.DeleteObject( this ); + if (m_grabbed) + { + wxASSERT_MSG( FALSE, _T("Window still grabbed")); + RemoveGrab(); + } - if (wxTheApp->GetTopWindow() == this) - wxTheApp->SetTopWindow( (wxWindow*) NULL ); + m_isBeingDeleted = TRUE; - if ((wxTopLevelWindows.Number() == 0) && - (wxTheApp->GetExitOnFrameDelete())) + // it may also be GtkScrolledWindow in the case of an MDI child + if (GTK_IS_WINDOW(m_widget)) { - wxTheApp->ExitMainLoop(); + gtk_window_set_focus( GTK_WINDOW(m_widget), NULL ); } } + + bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style ) { 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) { - m_fsSaveStyle = m_windowStyle; m_fsSaveFlag = style; GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y ); GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height ); - gtk_widget_hide( m_widget ); - gtk_widget_unrealize( m_widget ); + int screen_width,screen_height; + wxDisplaySize( &screen_width, &screen_height ); - m_windowStyle = wxSIMPLE_BORDER; + gint client_x, client_y, root_x, root_y; + gint width, height; - int x; - int y; - wxDisplaySize( &x, &y ); - SetSize( 0, 0, x, y ); + 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); + } - gtk_widget_realize( m_widget ); - gtk_widget_show( m_widget ); + 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 { - gtk_widget_hide( m_widget ); - gtk_widget_unrealize( m_widget ); - - m_windowStyle = m_fsSaveStyle; + 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); + } - 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); - gtk_widget_realize( m_widget ); - gtk_widget_show( m_widget ); + SetSize(m_fsSaveFrame.x, m_fsSaveFrame.y, + m_fsSaveFrame.width, m_fsSaveFrame.height); } + return TRUE; } @@ -586,10 +608,10 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si { wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); - /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */ + // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") ); - /* avoid recursions */ + // avoid recursions if (m_resizing) return; m_resizing = TRUE; @@ -604,16 +626,14 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si { if (x != -1) m_x = x; if (y != -1) m_y = y; - if (width != -1) m_width = width; - if (height != -1) m_height = height; } else { m_x = x; m_y = y; - m_width = width; - m_height = height; } + if (width != -1) m_width = width; + if (height != -1) m_height = height; /* if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH) @@ -627,10 +647,15 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si } */ - if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth; - if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight; - if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth; - if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight; + int minWidth = GetMinWidth(), + minHeight = GetMinHeight(), + maxWidth = GetMaxWidth(), + maxHeight = GetMaxHeight(); + + 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; + if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight; if ((m_x != -1) || (m_y != -1)) { @@ -642,7 +667,10 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si if ((m_width != old_width) || (m_height != old_height)) { - gtk_widget_set_usize( m_widget, m_width, m_height ); + if (m_widget->window) + gdk_window_resize( m_widget->window, m_width, m_height ); + else + gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height ); /* we set the size in GtkOnSize, i.e. mostly the actual resizing is done either directly before the frame is shown or in idle time @@ -660,7 +688,7 @@ void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const wxWindow::DoGetClientSize( width, height ); if (height) { - /* mini edge */ + // mini edge *height -= m_miniEdge*2 + m_miniTitle; } if (width) @@ -673,18 +701,18 @@ void wxTopLevelWindowGTK::DoSetClientSize( int width, int height ) { wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); - DoSetSize(-1, -1, + DoSetSize(-1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0); } void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), - int width, int height ) + int width, int height ) { // due to a bug in gtk, x,y are always 0 // m_x = x; // m_y = y; - /* avoid recursions */ + // avoid recursions if (m_resizing) return; m_resizing = TRUE; @@ -693,29 +721,57 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), m_width = width; m_height = height; - /* wxMDIChildFrame derives from wxFrameGTK but it _is_ a wxWindow as it uses + /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses wxWindow::Create to create it's GTK equivalent. m_mainWidget is only - set in wxFrameGTK::Create so it is used to check what kind of frame we + set in wxFrame::Create so it is used to check what kind of frame we have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we skip the part which handles m_frameMenuBar, m_frameToolBar and (most importantly) m_mainWidget */ - if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth; - if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight; - if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth; - if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight; + int minWidth = GetMinWidth(), + minHeight = GetMinHeight(), + maxWidth = GetMaxWidth(), + maxHeight = GetMaxHeight(); + + 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; + if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight; if (m_mainWidget) { - /* set size hints */ - gint flag = 0; // GDK_HINT_POS; - if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE; - if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE; - GdkGeometry geom; - geom.min_width = m_minWidth; - geom.min_height = m_minHeight; - geom.max_width = m_maxWidth; - geom.max_height = m_maxHeight; + // set size hints + gint flag = 0; // GDK_HINT_POS; + GdkGeometry geom; + + if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE; + if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE; + + geom.min_width = minWidth; + geom.min_height = minHeight; + + // Because of the way we set GDK_HINT_MAX_SIZE above, if either of + // maxHeight or maxWidth is set, we must set them both, else the + // remaining -1 will be taken literally. + + // I'm certain this also happens elsewhere, and is the probable + // cause of other such things as: + // 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. + + geom.max_width = ( maxHeight == -1 ) ? maxWidth + : ( maxWidth == -1 ) ? wxGetDisplaySize().GetWidth() + : maxWidth ; + + geom.max_height = ( maxWidth == -1 ) ? maxHeight // ( == -1 here ) + : ( maxHeight == -1 ) ? wxGetDisplaySize().GetHeight() + : maxHeight ; + gtk_window_set_geometry_hints( GTK_WINDOW(m_widget), (GtkWidget*) NULL, &geom, @@ -731,14 +787,15 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int client_y = m_miniEdge + m_miniTitle; int client_w = m_width - 2*m_miniEdge; int client_h = m_height - 2*m_miniEdge - m_miniTitle; + gtk_pizza_set_size( GTK_PIZZA(m_mainWidget), m_wxwindow, client_x, client_y, client_w, client_h ); } else { - /* if there is no m_mainWidget between m_widget and m_wxwindow there - is no need to set the size or position of m_wxwindow. */ + // If there is no m_mainWidget between m_widget and m_wxwindow there + // is no need to set the size or position of m_wxwindow. } m_sizeSet = TRUE; @@ -763,10 +820,25 @@ void wxTopLevelWindowGTK::OnInternalIdle() return; } + // set the focus if not done yet and if we can already do it + if ( GTK_WIDGET_REALIZED(m_wxwindow) ) + { + 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(); } - // ---------------------------------------------------------------------------- // frame title/icon // ---------------------------------------------------------------------------- @@ -776,16 +848,12 @@ void wxTopLevelWindowGTK::SetTitle( const wxString &title ) wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); m_title = title; - gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() ); + gtk_window_set_title( GTK_WINDOW(m_widget), wxGTK_CONV( title ) ); } -void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon ) +void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon ) { - wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); - - wxTopLevelWindowBase::SetIcon(icon); - - if ( !m_icon.Ok() ) + if ( !icon.Ok() ) return; if (!m_widget->window) @@ -798,13 +866,40 @@ void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon ) gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm ); } +void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon ) +{ + SetIcons( wxIconBundle( 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 ) + { + wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ), + (WXWindow)GDK_WINDOW_XWINDOW( window ), icons ); + } +} + // ---------------------------------------------------------------------------- // 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 @@ -817,11 +912,22 @@ bool wxTopLevelWindowGTK::IsMaximized() const void wxTopLevelWindowGTK::Restore() { +#ifdef __GTK20__ + // "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; @@ -833,6 +939,7 @@ void wxTopLevelWindowGTK::Iconize( bool iconize ) GDK_WINDOW_XWINDOW( window ), DefaultScreen( GDK_DISPLAY() ) ); } +#endif } bool wxTopLevelWindowGTK::IsIconized() const @@ -849,3 +956,66 @@ void wxTopLevelWindowGTK::SetIconizeState(bool iconize) } } +void wxTopLevelWindowGTK::AddGrab() +{ + if (!m_grabbed) + { + m_grabbed = TRUE; + gtk_grab_add( m_widget ); + gtk_main(); + gtk_grab_remove( m_widget ); + } +} + +void wxTopLevelWindowGTK::RemoveGrab() +{ + if (m_grabbed) + { + gtk_main_quit(); + m_grabbed = FALSE; + } +} + + +// 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); +} + +// vi:sts=4:sw=4:et