X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a56fcaaf46ccce9f6f79b8fad977dfe5a721ea61..dd107c50be43e8d4dbdba20df162faf119a3781c:/src/gtk/frame.cpp diff --git a/src/gtk/frame.cpp b/src/gtk/frame.cpp index 301a3b309d..cedfca99d5 100644 --- a/src/gtk/frame.cpp +++ b/src/gtk/frame.cpp @@ -19,6 +19,10 @@ #pragma implementation "frame.h" #endif +#ifdef __VMS +#define XIconifyWindow XICONIFYWINDOW +#endif + #include "wx/frame.h" #include "wx/dialog.h" #include "wx/control.h" @@ -126,6 +130,7 @@ 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(); } } @@ -241,47 +246,51 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *ev /* we cannot MWM hints and icons before the widget has been realized, so we do this directly after realization */ -static gint -gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win ) +static void +gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxFrame *win ) { if (g_isIdle) wxapp_install_idle_handler(); - /* I haven't been able to set the position of - the dialog before it is shown, so I set the - position in "realize" */ - gtk_widget_set_uposition( widget, win->m_x, win->m_y ); - - /* 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) + if ((win->m_miniEdge > 0) || (win->HasFlag(wxSIMPLE_BORDER)) || (win->HasFlag(wxNO_BORDER))) { - func |= GDK_FUNC_MAXIMIZE; - decor |= GDK_DECOR_MAXIMIZE; + /* 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 ); } - if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0) + else { - func |= GDK_FUNC_RESIZE; - decor |= GDK_DECOR_RESIZEH; - } + /* 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); + gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor); + gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func); + } /* GTK's shrinking/growing policy */ if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0) @@ -289,19 +298,6 @@ gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win ) else gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1); - /* set size hints */ - gint flag = 0; // GDK_HINT_POS; - if ((win->GetMinWidth() != -1) || (win->GetMinHeight() != -1)) flag |= GDK_HINT_MIN_SIZE; - if ((win->GetMaxWidth() != -1) || (win->GetMaxHeight() != -1)) flag |= GDK_HINT_MAX_SIZE; - if (flag) - { - gdk_window_set_hints( win->m_widget->window, - win->m_x, win->m_y, - win->GetMinWidth(), win->GetMinHeight(), - win->GetMaxWidth(), win->GetMaxHeight(), - flag ); - } - /* reset the icon */ wxIcon iconOld = win->GetIcon(); if ( iconOld != wxNullIcon ) @@ -325,8 +321,57 @@ gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win ) node = node->GetNext(); } +} - return FALSE; +//----------------------------------------------------------------------------- +// "map_event" from m_widget +//----------------------------------------------------------------------------- + +static void +gtk_frame_map_callback( GtkWidget * WXUNUSED(widget), + GdkEvent * WXUNUSED(event), + wxFrame *win ) +{ + win->SetIconizeState(FALSE); +} + +//----------------------------------------------------------------------------- +// "unmap_event" from m_widget +//----------------------------------------------------------------------------- + +static void +gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget), + GdkEvent * WXUNUSED(event), + wxFrame *win ) +{ + win->SetIconizeState(TRUE); +} + +//----------------------------------------------------------------------------- +// "expose_event" of m_client +//----------------------------------------------------------------------------- + +static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win ) +{ + 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); + + return TRUE; +} + +//----------------------------------------------------------------------------- +// "draw" of m_client +//----------------------------------------------------------------------------- + + +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); } // ---------------------------------------------------------------------------- @@ -403,16 +448,31 @@ void wxFrame::Init() m_toolBarDetached = FALSE; m_insertInClientArea = TRUE; m_isFrame = TRUE; + m_isIconized = TRUE; + m_fsIsShowing = FALSE; + m_themeEnabled = TRUE; } bool wxFrame::Create( wxWindow *parent, wxWindowID id, - const wxString &title, - const wxPoint &pos, - const wxSize &size, + 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) + 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; + } + wxTopLevelWindows.Append( this ); m_needParent = FALSE; @@ -429,10 +489,15 @@ bool wxFrame::Create( wxWindow *parent, m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame; GtkWindowType win_type = GTK_WINDOW_TOPLEVEL; - if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP; + + if (style & wxFRAME_TOOL_WINDOW) + win_type = GTK_WINDOW_POPUP; m_widget = gtk_window_new( win_type ); + if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget))) + 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() ); @@ -452,6 +517,12 @@ bool wxFrame::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", + GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this ); + 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("wxFrame::m_mainWidget"), name ); #endif @@ -466,7 +537,7 @@ bool wxFrame::Create( wxWindow *parent, #endif /* we donm't allow the frame to get the focus as otherwise - the frame will grabit at arbitrary fcous changes. */ + 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 ); @@ -477,6 +548,10 @@ bool wxFrame::Create( wxWindow *parent, PostCreation(); + 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_signal_connect( GTK_OBJECT(m_widget), "realize", @@ -486,6 +561,16 @@ bool wxFrame::Create( wxWindow *parent, 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 ); + 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 */ + gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event", + GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this ); + /* disable native tab traversal */ gtk_signal_connect( GTK_OBJECT(m_widget), "focus", GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this ); @@ -511,6 +596,48 @@ wxFrame::~wxFrame() } } +bool wxFrame::ShowFullScreen(bool show, long style ) +{ + if (show == m_fsIsShowing) return FALSE; // return what? + + m_fsIsShowing = show; + + 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 ); + + m_windowStyle = wxSIMPLE_BORDER; + + int x; + int y; + wxDisplaySize( &x, &y ); + SetSize( 0, 0, x, y ); + + gtk_widget_realize( m_widget ); + gtk_widget_show( m_widget ); + } + else + { + gtk_widget_hide( m_widget ); + gtk_widget_unrealize( m_widget ); + + m_windowStyle = m_fsSaveStyle; + + SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height ); + + gtk_widget_realize( m_widget ); + gtk_widget_show( m_widget ); + } + + return TRUE; +} + // ---------------------------------------------------------------------------- // overridden wxWindow methods // ---------------------------------------------------------------------------- @@ -536,7 +663,7 @@ void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width) { wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") ); } - + void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags ) { wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); @@ -597,6 +724,8 @@ void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags ) if ((m_width != old_width) || (m_height != old_height)) { + gtk_widget_set_usize( 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 so that different calls to SetSize() don't lead to flicker. */ @@ -624,12 +753,12 @@ void wxFrame::DoGetClientSize( int *width, int *height ) const #if wxUSE_STATUSBAR /* status bar */ - if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT; + if (m_frameStatusBar && m_frameStatusBar->IsShown()) (*height) -= wxSTATUS_HEIGHT; #endif // wxUSE_STATUSBAR #if wxUSE_TOOLBAR /* tool bar */ - if (m_frameToolBar) + if (m_frameToolBar && m_frameToolBar->IsShown()) { if (m_toolBarDetached) { @@ -675,12 +804,12 @@ void wxFrame::DoSetClientSize( int width, int height ) #if wxUSE_STATUSBAR /* status bar */ - if (m_frameStatusBar) height += wxSTATUS_HEIGHT; + if (m_frameStatusBar && m_frameStatusBar->IsShown()) height += wxSTATUS_HEIGHT; #endif #if wxUSE_TOOLBAR /* tool bar */ - if (m_frameToolBar) + if (m_frameToolBar && m_frameToolBar->IsShown()) { if (m_toolBarDetached) { @@ -733,13 +862,26 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), 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; + if (m_mainWidget) { - /* check if size is in legal range */ - 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; + /* 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; + gtk_window_set_geometry_hints( GTK_WINDOW(m_widget), + (GtkWidget*) NULL, + &geom, + (GdkWindowHints) flag ); /* I revert back to wxGTK's original behaviour. m_mainWidget holds the * menubar, the toolbar and the client area, which is represented by @@ -765,7 +907,7 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), } #if wxUSE_TOOLBAR - if ((m_frameToolBar) && + if ((m_frameToolBar) && m_frameToolBar->IsShown() && (m_frameToolBar->m_widget->parent == m_mainWidget)) { int xx = m_miniEdge; @@ -821,7 +963,7 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), } #if wxUSE_STATUSBAR - if (m_frameStatusBar) + if (m_frameStatusBar && m_frameStatusBar->IsShown()) { int xx = 0 + m_miniEdge; int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset; @@ -834,12 +976,10 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), gtk_pizza_set_size( GTK_PIZZA(m_wxwindow), m_frameStatusBar->m_widget, xx, yy, ww, hh ); + gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL ); } #endif - /* we actually set the size of a frame here and no-where else */ - gtk_widget_set_usize( m_widget, m_width, m_height ); - m_sizeSet = TRUE; // send size event to frame @@ -898,33 +1038,51 @@ void wxFrame::SetMenuBar( wxMenuBar *menuBar ) wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") ); + if (menuBar == m_frameMenuBar) + return; + + if (m_frameMenuBar) + { + m_frameMenuBar->UnsetInvokingWindow( this ); + + if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE) + { + gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget), + GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this ); + + gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget), + GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this ); + } + + gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget ); + gtk_widget_ref( m_frameMenuBar->m_widget ); + gtk_widget_unparent( m_frameMenuBar->m_widget ); + } + m_frameMenuBar = menuBar; if (m_frameMenuBar) { m_frameMenuBar->SetInvokingWindow( this ); - if (m_frameMenuBar->GetParent() != this) - { - m_frameMenuBar->SetParent(this); - gtk_pizza_put( GTK_PIZZA(m_mainWidget), + m_frameMenuBar->SetParent(this); + gtk_pizza_put( GTK_PIZZA(m_mainWidget), m_frameMenuBar->m_widget, m_frameMenuBar->m_x, m_frameMenuBar->m_y, m_frameMenuBar->m_width, m_frameMenuBar->m_height ); - if (menuBar->GetWindowStyle() & wxMB_DOCKABLE) - { - gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached", - GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this ); - - gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached", - GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this ); - } + if (menuBar->GetWindowStyle() & wxMB_DOCKABLE) + { + gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached", + GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this ); - m_frameMenuBar->Show( TRUE ); + gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached", + GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this ); } + + m_frameMenuBar->Show( TRUE ); } /* resize window in OnInternalIdle */ @@ -940,9 +1098,6 @@ wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& na m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name ); - if (m_frameToolBar) - GetChildren().DeleteObject( m_frameToolBar ); - m_insertInClientArea = TRUE; m_sizeSet = FALSE; @@ -1026,20 +1181,25 @@ void wxFrame::SetIcon( const wxIcon &icon ) } // ---------------------------------------------------------------------------- -// frame state: maximized/iconized/normal (TODO) +// frame state: maximized/iconized/normal // ---------------------------------------------------------------------------- void wxFrame::Maximize(bool WXUNUSED(maximize)) { + wxFAIL_MSG( _T("not implemented") ); } bool wxFrame::IsMaximized() const { + // wxFAIL_MSG( _T("not implemented") ); + + // This is an approximation return FALSE; } void wxFrame::Restore() { + wxFAIL_MSG( _T("not implemented") ); } void wxFrame::Iconize( bool iconize ) @@ -1054,5 +1214,21 @@ void wxFrame::Iconize( bool iconize ) bool wxFrame::IsIconized() const { - return FALSE; + return m_isIconized; } + +void wxFrame::SetIconizeState(bool iconize) +{ + if ( iconize != m_isIconized ) + { + m_isIconized = iconize; + (void)SendIconizeEvent(iconize); + } + else + { + // this is not supposed to happen if we're called only from + // gtk_frame_(un)map_callback! + wxFAIL_MSG( _T("unexpected call to SendIconizeEvent ignored") ); + } +} +