1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
19 #pragma implementation "frame.h"
23 #define XIconifyWindow XICONIFYWINDOW
27 #include "wx/dialog.h"
28 #include "wx/control.h"
32 #include "wx/toolbar.h"
35 #include "wx/statusbr.h"
37 #include "wx/dcclient.h"
42 #include <gdk/gdkkeysyms.h>
45 #include "wx/gtk/win_gtk.h"
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 const int wxMENU_HEIGHT
= 27;
52 const int wxSTATUS_HEIGHT
= 25;
53 const int wxPLACE_HOLDER
= 0;
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 extern void wxapp_install_idle_handler();
61 extern int g_openDialogs
;
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 IMPLEMENT_DYNAMIC_CLASS(wxFrame
,wxWindow
)
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 extern wxList wxPendingDelete
;
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
81 extern void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
);
85 // ============================================================================
87 // ============================================================================
89 // ----------------------------------------------------------------------------
91 // ----------------------------------------------------------------------------
93 //-----------------------------------------------------------------------------
94 // "focus" from m_window
95 //-----------------------------------------------------------------------------
97 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
100 wxapp_install_idle_handler();
102 // This disables GTK's tab traversal
103 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
107 //-----------------------------------------------------------------------------
109 //-----------------------------------------------------------------------------
111 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxFrame
*win
)
114 wxapp_install_idle_handler();
119 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
122 wxPrintf( "OnSize from " );
123 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
124 wxPrintf( win->GetClassInfo()->GetClassName() );
125 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
128 (int)alloc->height );
131 win
->m_width
= alloc
->width
;
132 win
->m_height
= alloc
->height
;
133 win
->m_queuedFullRedraw
= TRUE
;
134 win
->GtkUpdateSize();
138 //-----------------------------------------------------------------------------
140 //-----------------------------------------------------------------------------
142 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxFrame
*win
)
145 wxapp_install_idle_handler();
147 if ((g_openDialogs
== 0) && (win
->IsEnabled()))
153 //-----------------------------------------------------------------------------
154 // "child_attached" of menu bar
155 //-----------------------------------------------------------------------------
157 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
159 if (!win
->m_hasVMT
) return;
161 win
->m_menuBarDetached
= FALSE
;
162 win
->GtkUpdateSize();
165 //-----------------------------------------------------------------------------
166 // "child_detached" of menu bar
167 //-----------------------------------------------------------------------------
169 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
171 if (!win
->m_hasVMT
) return;
173 win
->m_menuBarDetached
= TRUE
;
174 win
->GtkUpdateSize();
178 //-----------------------------------------------------------------------------
179 // "child_attached" of tool bar
180 //-----------------------------------------------------------------------------
182 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
184 if (!win
->m_hasVMT
) return;
186 win
->m_toolBarDetached
= FALSE
;
188 win
->GtkUpdateSize();
191 //-----------------------------------------------------------------------------
192 // "child_detached" of tool bar
193 //-----------------------------------------------------------------------------
195 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
198 wxapp_install_idle_handler();
200 if (!win
->m_hasVMT
) return;
202 win
->m_toolBarDetached
= TRUE
;
203 win
->GtkUpdateSize();
205 #endif // wxUSE_TOOLBAR
207 //-----------------------------------------------------------------------------
209 //-----------------------------------------------------------------------------
212 #if (GTK_MINOR_VERSION > 0)
213 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxFrame
*win
)
215 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*event
, wxFrame
*win
)
219 wxapp_install_idle_handler();
224 #if (GTK_MINOR_VERSION > 0)
227 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
235 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
236 mevent
.SetEventObject( win
);
237 win
->GetEventHandler()->ProcessEvent( mevent
);
242 //-----------------------------------------------------------------------------
243 // "realize" from m_widget
244 //-----------------------------------------------------------------------------
246 /* we cannot MWM hints and icons before the widget has been realized,
247 so we do this directly after realization */
250 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
), wxFrame
*win
)
253 wxapp_install_idle_handler();
255 if ((win
->m_miniEdge
> 0) || (win
->HasFlag(wxSIMPLE_BORDER
)) || (win
->HasFlag(wxNO_BORDER
)))
257 /* This is a mini-frame or a borderless frame. */
258 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)0 );
259 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)0 );
263 /* All this is for Motif Window Manager "hints" and is supposed to be
264 recognized by other WM as well. Not tested. */
265 long decor
= (long) GDK_DECOR_BORDER
;
266 long func
= (long) GDK_FUNC_MOVE
;
268 if ((win
->GetWindowStyle() & wxCAPTION
) != 0)
269 decor
|= GDK_DECOR_TITLE
;
270 if ((win
->GetWindowStyle() & wxSYSTEM_MENU
) != 0)
272 decor
|= GDK_DECOR_MENU
;
273 func
|= GDK_FUNC_CLOSE
;
275 if ((win
->GetWindowStyle() & wxMINIMIZE_BOX
) != 0)
277 func
|= GDK_FUNC_MINIMIZE
;
278 decor
|= GDK_DECOR_MINIMIZE
;
280 if ((win
->GetWindowStyle() & wxMAXIMIZE_BOX
) != 0)
282 func
|= GDK_FUNC_MAXIMIZE
;
283 decor
|= GDK_DECOR_MAXIMIZE
;
285 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) != 0)
287 func
|= GDK_FUNC_RESIZE
;
288 decor
|= GDK_DECOR_RESIZEH
;
291 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)decor
);
292 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)func
);
295 /* GTK's shrinking/growing policy */
296 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) == 0)
297 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
299 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
302 wxIcon iconOld
= win
->GetIcon();
303 if ( iconOld
!= wxNullIcon
)
305 wxIcon
icon( iconOld
);
306 win
->SetIcon( wxNullIcon
);
307 win
->SetIcon( icon
);
310 /* we set the focus to the child that accepts the focus. this
311 doesn't really have to be done in "realize" but why not? */
312 wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
315 wxWindow
*child
= node
->GetData();
316 if (child
->AcceptsFocus())
322 node
= node
->GetNext();
326 //-----------------------------------------------------------------------------
327 // "map_event" from m_widget
328 //-----------------------------------------------------------------------------
331 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
332 GdkEvent
* WXUNUSED(event
),
335 win
->SetIconizeState(FALSE
);
338 //-----------------------------------------------------------------------------
339 // "unmap_event" from m_widget
340 //-----------------------------------------------------------------------------
343 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
344 GdkEvent
* WXUNUSED(event
),
347 win
->SetIconizeState(TRUE
);
350 //-----------------------------------------------------------------------------
351 // "expose_event" of m_client
352 //-----------------------------------------------------------------------------
354 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
356 GtkPizza
*pizza
= GTK_PIZZA(widget
);
358 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
359 GTK_SHADOW_NONE
, &gdk_event
->area
, win
->m_widget
, "base", 0, 0, -1, -1);
364 //-----------------------------------------------------------------------------
365 // "draw" of m_client
366 //-----------------------------------------------------------------------------
369 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
371 GtkPizza
*pizza
= GTK_PIZZA(widget
);
373 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
374 GTK_SHADOW_NONE
, rect
, win
->m_widget
, "base", 0, 0, -1, -1);
377 // ----------------------------------------------------------------------------
379 // ----------------------------------------------------------------------------
381 //-----------------------------------------------------------------------------
382 // InsertChild for wxFrame
383 //-----------------------------------------------------------------------------
385 /* Callback for wxFrame. This very strange beast has to be used because
386 * C++ has no virtual methods in a constructor. We have to emulate a
387 * virtual function here as wxWindows requires different ways to insert
388 * a child in container classes. */
390 static void wxInsertChildInFrame( wxFrame
* parent
, wxWindow
* child
)
392 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
394 if (!parent
->m_insertInClientArea
)
396 /* these are outside the client area */
397 wxFrame
* frame
= (wxFrame
*) parent
;
398 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
399 GTK_WIDGET(child
->m_widget
),
405 #if wxUSE_TOOLBAR_NATIVE
406 /* we connect to these events for recalculating the client area
407 space when the toolbar is floating */
408 if (wxIS_KIND_OF(child
,wxToolBar
))
410 wxToolBar
*toolBar
= (wxToolBar
*) child
;
411 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
413 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
414 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
416 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
417 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
420 #endif // wxUSE_TOOLBAR
424 /* these are inside the client area */
425 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
426 GTK_WIDGET(child
->m_widget
),
433 /* resize on OnInternalIdle */
434 parent
->GtkUpdateSize();
437 // ----------------------------------------------------------------------------
439 // ----------------------------------------------------------------------------
446 m_mainWidget
= (GtkWidget
*) NULL
;
447 m_menuBarDetached
= FALSE
;
448 m_toolBarDetached
= FALSE
;
449 m_insertInClientArea
= TRUE
;
451 m_isIconized
= FALSE
;
452 m_fsIsShowing
= FALSE
;
453 m_themeEnabled
= TRUE
;
456 bool wxFrame::Create( wxWindow
*parent
,
458 const wxString
& title
,
460 const wxSize
& sizeOrig
,
462 const wxString
&name
)
464 // always create a frame of some reasonable, even if arbitrary, size (at
465 // least for MSW compatibility)
466 wxSize size
= sizeOrig
;
467 if ( size
.x
== -1 || size
.y
== -1 )
469 wxSize sizeDpy
= wxGetDisplaySize();
471 size
.x
= sizeDpy
.x
/ 3;
473 size
.y
= sizeDpy
.y
/ 5;
476 wxTopLevelWindows
.Append( this );
478 m_needParent
= FALSE
;
480 if (!PreCreation( parent
, pos
, size
) ||
481 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
483 wxFAIL_MSG( wxT("wxFrame creation failed") );
489 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
491 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
493 if (style
& wxFRAME_TOOL_WINDOW
)
494 win_type
= GTK_WINDOW_POPUP
;
496 m_widget
= gtk_window_new( win_type
);
498 if ((m_parent
) && (HasFlag(wxFRAME_FLOAT_ON_PARENT
)) && (GTK_IS_WINDOW(m_parent
->m_widget
)))
499 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
502 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), name
.mb_str(), name
.mb_str() );
505 debug_focus_in( m_widget
, wxT("wxFrame::m_widget"), name
);
508 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
509 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
511 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
512 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
514 /* m_mainWidget holds the toolbar, the menubar and the client area */
515 m_mainWidget
= gtk_pizza_new();
516 gtk_widget_show( m_mainWidget
);
517 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
518 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
520 /* for m_mainWidget themes */
521 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
522 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
523 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
524 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
527 debug_focus_in( m_mainWidget
, wxT("wxFrame::m_mainWidget"), name
);
530 /* m_wxwindow only represents the client area without toolbar and menubar */
531 m_wxwindow
= gtk_pizza_new();
532 gtk_widget_show( m_wxwindow
);
533 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
536 debug_focus_in( m_wxwindow
, wxT("wxFrame::m_wxwindow"), name
);
539 /* we donm't allow the frame to get the focus as otherwise
540 the frame will grab it at arbitrary focus changes. */
541 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
543 if (m_parent
) m_parent
->AddChild( this );
545 /* the user resized the frame by dragging etc. */
546 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
547 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
551 if ((m_x
!= -1) || (m_y
!= -1))
552 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
553 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
555 /* we cannot set MWM hints and icons before the widget has
556 been realized, so we do this directly after realization */
557 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
558 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
560 /* the only way to get the window size is to connect to this event */
561 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
562 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
564 /* map and unmap for iconized state */
565 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
566 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
567 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
568 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
570 /* the only way to get the window size is to connect to this event */
571 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
572 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
574 /* disable native tab traversal */
575 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
576 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
583 m_isBeingDeleted
= TRUE
;
587 wxTopLevelWindows
.DeleteObject( this );
589 if (wxTheApp
->GetTopWindow() == this)
590 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
592 if ((wxTopLevelWindows
.Number() == 0) &&
593 (wxTheApp
->GetExitOnFrameDelete()))
595 wxTheApp
->ExitMainLoop();
599 bool wxFrame::ShowFullScreen(bool show
, long style
)
601 if (show
== m_fsIsShowing
) return FALSE
; // return what?
603 m_fsIsShowing
= show
;
607 m_fsSaveStyle
= m_windowStyle
;
608 m_fsSaveFlag
= style
;
609 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
610 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
612 gtk_widget_hide( m_widget
);
613 gtk_widget_unrealize( m_widget
);
615 m_windowStyle
= wxSIMPLE_BORDER
;
619 wxDisplaySize( &x
, &y
);
620 SetSize( 0, 0, x
, y
);
622 gtk_widget_realize( m_widget
);
623 gtk_widget_show( m_widget
);
627 gtk_widget_hide( m_widget
);
628 gtk_widget_unrealize( m_widget
);
630 m_windowStyle
= m_fsSaveStyle
;
632 SetSize( m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
634 gtk_widget_realize( m_widget
);
635 gtk_widget_show( m_widget
);
641 // ----------------------------------------------------------------------------
642 // overridden wxWindow methods
643 // ----------------------------------------------------------------------------
645 bool wxFrame::Show( bool show
)
647 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
649 if (show
&& !m_sizeSet
)
651 /* by calling GtkOnSize here, we don't have to call
652 either after showing the frame, which would entail
653 much ugly flicker or from within the size_allocate
654 handler, because GTK 1.1.X forbids that. */
656 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
659 return wxWindow::Show( show
);
662 void wxFrame::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
664 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
667 void wxFrame::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
669 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
671 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
672 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
674 /* avoid recursions */
682 int old_width
= m_width
;
683 int old_height
= m_height
;
685 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
687 if (x
!= -1) m_x
= x
;
688 if (y
!= -1) m_y
= y
;
689 if (width
!= -1) m_width
= width
;
690 if (height
!= -1) m_height
= height
;
701 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
703 if (width == -1) m_width = 80;
706 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
708 if (height == -1) m_height = 26;
712 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
713 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
714 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
715 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
717 if ((m_x
!= -1) || (m_y
!= -1))
719 if ((m_x
!= old_x
) || (m_y
!= old_y
))
721 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
725 if ((m_width
!= old_width
) || (m_height
!= old_height
))
727 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
729 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
730 done either directly before the frame is shown or in idle time
731 so that different calls to SetSize() don't lead to flicker. */
738 void wxFrame::DoGetClientSize( int *width
, int *height
) const
740 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
742 wxWindow::DoGetClientSize( width
, height
);
748 if (!m_menuBarDetached
)
749 (*height
) -= wxMENU_HEIGHT
;
751 (*height
) -= wxPLACE_HOLDER
;
756 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) (*height
) -= wxSTATUS_HEIGHT
;
757 #endif // wxUSE_STATUSBAR
761 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
763 if (m_toolBarDetached
)
765 *height
-= wxPLACE_HOLDER
;
770 m_frameToolBar
->GetSize( &x
, &y
);
771 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
781 #endif // wxUSE_TOOLBAR
784 *height
-= m_miniEdge
*2 + m_miniTitle
;
788 *width
-= m_miniEdge
*2;
792 void wxFrame::DoSetClientSize( int width
, int height
)
794 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
799 if (!m_menuBarDetached
)
800 height
+= wxMENU_HEIGHT
;
802 height
+= wxPLACE_HOLDER
;
807 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
812 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
814 if (m_toolBarDetached
)
816 height
+= wxPLACE_HOLDER
;
821 m_frameToolBar
->GetSize( &x
, &y
);
822 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
834 DoSetSize( -1, -1, width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0 );
837 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
838 int width
, int height
)
840 // due to a bug in gtk, x,y are always 0
844 /* avoid recursions */
845 if (m_resizing
) return;
848 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
849 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
854 /* space occupied by m_frameToolBar and m_frameMenuBar */
855 int client_area_x_offset
= 0,
856 client_area_y_offset
= 0;
858 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
859 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
860 set in wxFrame::Create so it is used to check what kind of frame we
861 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
862 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
863 importantly) m_mainWidget */
865 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
866 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
867 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
868 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
873 gint flag
= 0; // GDK_HINT_POS;
874 if ((m_minWidth
!= -1) || (m_minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
875 if ((m_maxWidth
!= -1) || (m_maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
877 geom
.min_width
= m_minWidth
;
878 geom
.min_height
= m_minHeight
;
879 geom
.max_width
= m_maxWidth
;
880 geom
.max_height
= m_maxHeight
;
881 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
884 (GdkWindowHints
) flag
);
886 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
887 * menubar, the toolbar and the client area, which is represented by
889 * this hurts in the eye, but I don't want to call SetSize()
890 * because I don't want to call any non-native functions here. */
895 int yy
= m_miniEdge
+ m_miniTitle
;
896 int ww
= m_width
- 2*m_miniEdge
;
897 int hh
= wxMENU_HEIGHT
;
898 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
899 m_frameMenuBar
->m_x
= xx
;
900 m_frameMenuBar
->m_y
= yy
;
901 m_frameMenuBar
->m_width
= ww
;
902 m_frameMenuBar
->m_height
= hh
;
903 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
904 m_frameMenuBar
->m_widget
,
906 client_area_y_offset
+= hh
;
910 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
911 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
914 int yy
= m_miniEdge
+ m_miniTitle
;
917 if (!m_menuBarDetached
)
920 yy
+= wxPLACE_HOLDER
;
923 m_frameToolBar
->m_x
= xx
;
924 m_frameToolBar
->m_y
= yy
;
926 /* don't change the toolbar's reported height/width */
928 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
930 ww
= m_toolBarDetached
? wxPLACE_HOLDER
931 : m_frameToolBar
->m_width
;
932 hh
= m_height
- 2*m_miniEdge
;
934 client_area_x_offset
+= ww
;
938 ww
= m_width
- 2*m_miniEdge
;
939 hh
= m_toolBarDetached
? wxPLACE_HOLDER
940 : m_frameToolBar
->m_height
;
942 client_area_y_offset
+= hh
;
945 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
946 m_frameToolBar
->m_widget
,
949 #endif // wxUSE_TOOLBAR
951 int client_x
= client_area_x_offset
+ m_miniEdge
;
952 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
953 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
954 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
955 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
957 client_x
, client_y
, client_w
, client_h
);
961 /* if there is no m_mainWidget between m_widget and m_wxwindow there
962 is no need to set the size or position of m_wxwindow. */
966 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
968 int xx
= 0 + m_miniEdge
;
969 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
970 int ww
= m_width
- 2*m_miniEdge
;
971 int hh
= wxSTATUS_HEIGHT
;
972 m_frameStatusBar
->m_x
= xx
;
973 m_frameStatusBar
->m_y
= yy
;
974 m_frameStatusBar
->m_width
= ww
;
975 m_frameStatusBar
->m_height
= hh
;
976 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
977 m_frameStatusBar
->m_widget
,
979 gtk_widget_draw( m_frameStatusBar
->m_widget
, (GdkRectangle
*) NULL
);
985 // send size event to frame
986 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
987 event
.SetEventObject( this );
988 GetEventHandler()->ProcessEvent( event
);
990 // send size event to status bar
991 if (m_frameStatusBar
)
993 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
994 event2
.SetEventObject( m_frameStatusBar
);
995 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
1001 void wxFrame::MakeModal( bool modal
)
1004 gtk_grab_add( m_widget
);
1006 gtk_grab_remove( m_widget
);
1009 void wxFrame::OnInternalIdle()
1011 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1013 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1015 // we'll come back later
1017 wxapp_install_idle_handler();
1021 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
1023 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
1026 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
1029 wxWindow::OnInternalIdle();
1032 // ----------------------------------------------------------------------------
1033 // menu/tool/status bar stuff
1034 // ----------------------------------------------------------------------------
1036 void wxFrame::SetMenuBar( wxMenuBar
*menuBar
)
1038 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1039 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
1041 if (menuBar
== m_frameMenuBar
)
1046 m_frameMenuBar
->UnsetInvokingWindow( this );
1048 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1050 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1051 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1053 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1054 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1057 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
1058 gtk_widget_ref( m_frameMenuBar
->m_widget
);
1059 gtk_widget_unparent( m_frameMenuBar
->m_widget
);
1062 m_frameMenuBar
= menuBar
;
1066 m_frameMenuBar
->SetInvokingWindow( this );
1068 m_frameMenuBar
->SetParent(this);
1069 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
1070 m_frameMenuBar
->m_widget
,
1071 m_frameMenuBar
->m_x
,
1072 m_frameMenuBar
->m_y
,
1073 m_frameMenuBar
->m_width
,
1074 m_frameMenuBar
->m_height
);
1076 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1078 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
1079 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1081 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
1082 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1085 m_frameMenuBar
->Show( TRUE
);
1088 /* resize window in OnInternalIdle */
1093 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
1095 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1097 m_insertInClientArea
= FALSE
;
1099 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
1101 m_insertInClientArea
= TRUE
;
1105 return m_frameToolBar
;
1108 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
1110 wxFrameBase::SetToolBar(toolbar
);
1114 /* insert into toolbar area if not already there */
1115 if ((m_frameToolBar
->m_widget
->parent
) &&
1116 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
1118 GetChildren().DeleteObject( m_frameToolBar
);
1120 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
1126 #endif // wxUSE_TOOLBAR
1130 wxStatusBar
* wxFrame::CreateStatusBar(int number
,
1133 const wxString
& name
)
1135 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1137 // because it will change when toolbar is added
1140 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
1143 void wxFrame::PositionStatusBar()
1145 if ( !m_frameStatusBar
)
1150 #endif // wxUSE_STATUSBAR
1152 // ----------------------------------------------------------------------------
1154 // ----------------------------------------------------------------------------
1156 void wxFrame::SetTitle( const wxString
&title
)
1158 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1161 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
1164 void wxFrame::SetIcon( const wxIcon
&icon
)
1166 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1168 wxFrameBase::SetIcon(icon
);
1173 if (!m_widget
->window
)
1176 wxMask
*mask
= icon
.GetMask();
1177 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1178 if (mask
) bm
= mask
->GetBitmap();
1180 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1183 // ----------------------------------------------------------------------------
1184 // frame state: maximized/iconized/normal
1185 // ----------------------------------------------------------------------------
1187 void wxFrame::Maximize(bool WXUNUSED(maximize
))
1189 wxFAIL_MSG( _T("not implemented") );
1192 bool wxFrame::IsMaximized() const
1194 // wxFAIL_MSG( _T("not implemented") );
1196 // This is an approximation
1200 void wxFrame::Restore()
1202 wxFAIL_MSG( _T("not implemented") );
1205 void wxFrame::Iconize( bool iconize
)
1209 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget
->window
),
1210 GDK_WINDOW_XWINDOW( m_widget
->window
),
1211 DefaultScreen( GDK_DISPLAY() ) );
1215 bool wxFrame::IsIconized() const
1217 return m_isIconized
;
1220 void wxFrame::SetIconizeState(bool iconize
)
1222 if ( iconize
!= m_isIconized
)
1224 m_isIconized
= iconize
;
1225 (void)SendIconizeEvent(iconize
);
1229 // this is not supposed to happen if we're called only from
1230 // gtk_frame_(un)map_callback!
1232 // RR: I don't understand this test. Upon startup, the frame is
1233 // not iconized by default, it has just not been created
1235 ///wxFAIL_MSG( _T("unexpected call to SendIconizeEvent ignored") );