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
28 #include "wx/dialog.h"
29 #include "wx/control.h"
33 #include "wx/toolbar.h"
36 #include "wx/statusbr.h"
38 #include "wx/dcclient.h"
43 #include <gdk/gdkkeysyms.h>
46 #include "wx/gtk/win_gtk.h"
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 const int wxMENU_HEIGHT
= 27;
53 const int wxSTATUS_HEIGHT
= 25;
54 const int wxPLACE_HOLDER
= 0;
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 extern void wxapp_install_idle_handler();
62 extern int g_openDialogs
;
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 #ifndef __WXUNIVERSAL__
69 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxWindow
)
72 // ----------------------------------------------------------------------------
74 // ----------------------------------------------------------------------------
76 extern wxList wxPendingDelete
;
78 // ----------------------------------------------------------------------------
80 // ----------------------------------------------------------------------------
84 extern void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
);
88 // ============================================================================
90 // ============================================================================
92 // ----------------------------------------------------------------------------
94 // ----------------------------------------------------------------------------
96 //-----------------------------------------------------------------------------
97 // "focus" from m_window
98 //-----------------------------------------------------------------------------
100 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
103 wxapp_install_idle_handler();
105 // This disables GTK's tab traversal
106 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
110 //-----------------------------------------------------------------------------
112 //-----------------------------------------------------------------------------
114 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxFrameGTK
*win
)
117 wxapp_install_idle_handler();
122 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
125 wxPrintf( "OnSize from " );
126 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
127 wxPrintf( win->GetClassInfo()->GetClassName() );
128 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
131 (int)alloc->height );
134 win
->m_width
= alloc
->width
;
135 win
->m_height
= alloc
->height
;
136 win
->m_queuedFullRedraw
= TRUE
;
137 win
->GtkUpdateSize();
141 //-----------------------------------------------------------------------------
143 //-----------------------------------------------------------------------------
145 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxFrameGTK
*win
)
148 wxapp_install_idle_handler();
150 if ((g_openDialogs
== 0) && (win
->IsEnabled()))
156 #if wxUSE_MENUS_NATIVE
158 //-----------------------------------------------------------------------------
159 // "child_attached" of menu bar
160 //-----------------------------------------------------------------------------
162 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
164 if (!win
->m_hasVMT
) return;
166 win
->m_menuBarDetached
= FALSE
;
167 win
->GtkUpdateSize();
170 //-----------------------------------------------------------------------------
171 // "child_detached" of menu bar
172 //-----------------------------------------------------------------------------
174 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
176 if (!win
->m_hasVMT
) return;
178 win
->m_menuBarDetached
= TRUE
;
179 win
->GtkUpdateSize();
182 #endif // wxUSE_MENUS_NATIVE
185 //-----------------------------------------------------------------------------
186 // "child_attached" of tool bar
187 //-----------------------------------------------------------------------------
189 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
191 if (!win
->m_hasVMT
) return;
193 win
->m_toolBarDetached
= FALSE
;
195 win
->GtkUpdateSize();
198 //-----------------------------------------------------------------------------
199 // "child_detached" of tool bar
200 //-----------------------------------------------------------------------------
202 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
205 wxapp_install_idle_handler();
207 if (!win
->m_hasVMT
) return;
209 win
->m_toolBarDetached
= TRUE
;
210 win
->GtkUpdateSize();
212 #endif // wxUSE_TOOLBAR
214 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
219 #if (GTK_MINOR_VERSION > 0)
220 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxFrameGTK
*win
)
222 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*event
, wxFrameGTK
*win
)
226 wxapp_install_idle_handler();
231 #if (GTK_MINOR_VERSION > 0)
234 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
242 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
243 mevent
.SetEventObject( win
);
244 win
->GetEventHandler()->ProcessEvent( mevent
);
249 //-----------------------------------------------------------------------------
250 // "realize" from m_widget
251 //-----------------------------------------------------------------------------
253 /* we cannot MWM hints and icons before the widget has been realized,
254 so we do this directly after realization */
257 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
), wxFrameGTK
*win
)
260 wxapp_install_idle_handler();
262 if ((win
->m_miniEdge
> 0) || (win
->HasFlag(wxSIMPLE_BORDER
)) || (win
->HasFlag(wxNO_BORDER
)))
264 /* This is a mini-frame or a borderless frame. */
265 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)0 );
266 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)0 );
270 /* All this is for Motif Window Manager "hints" and is supposed to be
271 recognized by other WM as well. Not tested. */
272 long decor
= (long) GDK_DECOR_BORDER
;
273 long func
= (long) GDK_FUNC_MOVE
;
275 if ((win
->GetWindowStyle() & wxCAPTION
) != 0)
276 decor
|= GDK_DECOR_TITLE
;
277 if ((win
->GetWindowStyle() & wxSYSTEM_MENU
) != 0)
279 decor
|= GDK_DECOR_MENU
;
280 func
|= GDK_FUNC_CLOSE
;
282 if ((win
->GetWindowStyle() & wxMINIMIZE_BOX
) != 0)
284 func
|= GDK_FUNC_MINIMIZE
;
285 decor
|= GDK_DECOR_MINIMIZE
;
287 if ((win
->GetWindowStyle() & wxMAXIMIZE_BOX
) != 0)
289 func
|= GDK_FUNC_MAXIMIZE
;
290 decor
|= GDK_DECOR_MAXIMIZE
;
292 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) != 0)
294 func
|= GDK_FUNC_RESIZE
;
295 decor
|= GDK_DECOR_RESIZEH
;
298 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)decor
);
299 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)func
);
302 /* GTK's shrinking/growing policy */
303 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) == 0)
304 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
306 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
309 wxIcon iconOld
= win
->GetIcon();
310 if ( iconOld
!= wxNullIcon
)
312 wxIcon
icon( iconOld
);
313 win
->SetIcon( wxNullIcon
);
314 win
->SetIcon( icon
);
317 /* we set the focus to the child that accepts the focus. this
318 doesn't really have to be done in "realize" but why not? */
319 wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
322 wxWindow
*child
= node
->GetData();
323 if (child
->AcceptsFocus())
329 node
= node
->GetNext();
333 //-----------------------------------------------------------------------------
334 // "map_event" from m_widget
335 //-----------------------------------------------------------------------------
338 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
339 GdkEvent
* WXUNUSED(event
),
342 win
->SetIconizeState(FALSE
);
345 //-----------------------------------------------------------------------------
346 // "unmap_event" from m_widget
347 //-----------------------------------------------------------------------------
350 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
351 GdkEvent
* WXUNUSED(event
),
354 win
->SetIconizeState(TRUE
);
357 //-----------------------------------------------------------------------------
358 // "expose_event" of m_client
359 //-----------------------------------------------------------------------------
361 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
363 GtkPizza
*pizza
= GTK_PIZZA(widget
);
365 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
366 GTK_SHADOW_NONE
, &gdk_event
->area
, win
->m_widget
, "base", 0, 0, -1, -1);
371 //-----------------------------------------------------------------------------
372 // "draw" of m_client
373 //-----------------------------------------------------------------------------
376 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
378 GtkPizza
*pizza
= GTK_PIZZA(widget
);
380 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
381 GTK_SHADOW_NONE
, rect
, win
->m_widget
, "base", 0, 0, -1, -1);
384 // ----------------------------------------------------------------------------
386 // ----------------------------------------------------------------------------
388 //-----------------------------------------------------------------------------
389 // InsertChild for wxFrameGTK
390 //-----------------------------------------------------------------------------
392 /* Callback for wxFrameGTK. This very strange beast has to be used because
393 * C++ has no virtual methods in a constructor. We have to emulate a
394 * virtual function here as wxWindows requires different ways to insert
395 * a child in container classes. */
397 static void wxInsertChildInFrame( wxFrameGTK
* parent
, wxWindow
* child
)
399 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
401 if (!parent
->m_insertInClientArea
)
403 /* these are outside the client area */
404 wxFrameGTK
* frame
= (wxFrameGTK
*) parent
;
405 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
406 GTK_WIDGET(child
->m_widget
),
412 #if wxUSE_TOOLBAR_NATIVE
413 /* we connect to these events for recalculating the client area
414 space when the toolbar is floating */
415 if (wxIS_KIND_OF(child
,wxToolBar
))
417 wxToolBar
*toolBar
= (wxToolBar
*) child
;
418 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
420 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
421 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
423 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
424 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
427 #endif // wxUSE_TOOLBAR
431 /* these are inside the client area */
432 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
433 GTK_WIDGET(child
->m_widget
),
440 /* resize on OnInternalIdle */
441 parent
->GtkUpdateSize();
444 // ----------------------------------------------------------------------------
445 // wxFrameGTK creation
446 // ----------------------------------------------------------------------------
448 void wxFrameGTK::Init()
453 m_mainWidget
= (GtkWidget
*) NULL
;
454 m_menuBarDetached
= FALSE
;
455 m_toolBarDetached
= FALSE
;
456 m_insertInClientArea
= TRUE
;
458 m_isIconized
= FALSE
;
459 m_fsIsShowing
= FALSE
;
460 m_themeEnabled
= TRUE
;
463 bool wxFrameGTK::Create( wxWindow
*parent
,
465 const wxString
& title
,
467 const wxSize
& sizeOrig
,
469 const wxString
&name
)
471 // always create a frame of some reasonable, even if arbitrary, size (at
472 // least for MSW compatibility)
473 wxSize size
= sizeOrig
;
474 if ( size
.x
== -1 || size
.y
== -1 )
476 wxSize sizeDpy
= wxGetDisplaySize();
478 size
.x
= sizeDpy
.x
/ 3;
480 size
.y
= sizeDpy
.y
/ 5;
483 wxTopLevelWindows
.Append( this );
485 m_needParent
= FALSE
;
487 if (!PreCreation( parent
, pos
, size
) ||
488 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
490 wxFAIL_MSG( wxT("wxFrameGTK creation failed") );
496 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
498 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
500 if (style
& wxFRAME_TOOL_WINDOW
)
501 win_type
= GTK_WINDOW_POPUP
;
503 m_widget
= gtk_window_new( win_type
);
505 if ((m_parent
) && (HasFlag(wxFRAME_FLOAT_ON_PARENT
)) && (GTK_IS_WINDOW(m_parent
->m_widget
)))
506 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
509 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), name
.mb_str(), name
.mb_str() );
512 debug_focus_in( m_widget
, wxT("wxFrameGTK::m_widget"), name
);
515 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
516 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
518 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
519 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
521 /* m_mainWidget holds the toolbar, the menubar and the client area */
522 m_mainWidget
= gtk_pizza_new();
523 gtk_widget_show( m_mainWidget
);
524 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
525 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
527 /* for m_mainWidget themes */
528 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
529 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
530 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
531 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
534 debug_focus_in( m_mainWidget
, wxT("wxFrameGTK::m_mainWidget"), name
);
537 /* m_wxwindow only represents the client area without toolbar and menubar */
538 m_wxwindow
= gtk_pizza_new();
539 gtk_widget_show( m_wxwindow
);
540 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
543 debug_focus_in( m_wxwindow
, wxT("wxFrameGTK::m_wxwindow"), name
);
546 /* we donm't allow the frame to get the focus as otherwise
547 the frame will grab it at arbitrary focus changes. */
548 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
550 if (m_parent
) m_parent
->AddChild( this );
552 /* the user resized the frame by dragging etc. */
553 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
554 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
558 if ((m_x
!= -1) || (m_y
!= -1))
559 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
560 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
562 /* we cannot set MWM hints and icons before the widget has
563 been realized, so we do this directly after realization */
564 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
565 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
567 /* the only way to get the window size is to connect to this event */
568 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
569 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
571 /* map and unmap for iconized state */
572 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
573 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
574 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
575 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
577 /* the only way to get the window size is to connect to this event */
578 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
579 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
581 /* disable native tab traversal */
582 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
583 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
588 wxFrameGTK::~wxFrameGTK()
590 m_isBeingDeleted
= TRUE
;
594 wxTopLevelWindows
.DeleteObject( this );
596 if (wxTheApp
->GetTopWindow() == this)
597 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
599 if ((wxTopLevelWindows
.Number() == 0) &&
600 (wxTheApp
->GetExitOnFrameDelete()))
602 wxTheApp
->ExitMainLoop();
606 bool wxFrameGTK::ShowFullScreen(bool show
, long style
)
608 if (show
== m_fsIsShowing
) return FALSE
; // return what?
610 m_fsIsShowing
= show
;
614 m_fsSaveStyle
= m_windowStyle
;
615 m_fsSaveFlag
= style
;
616 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
617 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
619 gtk_widget_hide( m_widget
);
620 gtk_widget_unrealize( m_widget
);
622 m_windowStyle
= wxSIMPLE_BORDER
;
626 wxDisplaySize( &x
, &y
);
627 SetSize( 0, 0, x
, y
);
629 gtk_widget_realize( m_widget
);
630 gtk_widget_show( m_widget
);
634 gtk_widget_hide( m_widget
);
635 gtk_widget_unrealize( m_widget
);
637 m_windowStyle
= m_fsSaveStyle
;
639 SetSize( m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
641 gtk_widget_realize( m_widget
);
642 gtk_widget_show( m_widget
);
648 // ----------------------------------------------------------------------------
649 // overridden wxWindow methods
650 // ----------------------------------------------------------------------------
652 bool wxFrameGTK::Show( bool show
)
654 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
656 if (show
&& !m_sizeSet
)
658 /* by calling GtkOnSize here, we don't have to call
659 either after showing the frame, which would entail
660 much ugly flicker or from within the size_allocate
661 handler, because GTK 1.1.X forbids that. */
663 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
666 return wxWindow::Show( show
);
669 void wxFrameGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
671 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrameGTK") );
674 void wxFrameGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
676 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
678 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
679 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
681 /* avoid recursions */
689 int old_width
= m_width
;
690 int old_height
= m_height
;
692 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
694 if (x
!= -1) m_x
= x
;
695 if (y
!= -1) m_y
= y
;
696 if (width
!= -1) m_width
= width
;
697 if (height
!= -1) m_height
= height
;
708 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
710 if (width == -1) m_width = 80;
713 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
715 if (height == -1) m_height = 26;
719 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
720 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
721 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
722 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
724 if ((m_x
!= -1) || (m_y
!= -1))
726 if ((m_x
!= old_x
) || (m_y
!= old_y
))
728 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
732 if ((m_width
!= old_width
) || (m_height
!= old_height
))
734 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
736 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
737 done either directly before the frame is shown or in idle time
738 so that different calls to SetSize() don't lead to flicker. */
745 void wxFrameGTK::DoGetClientSize( int *width
, int *height
) const
747 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
749 wxWindow::DoGetClientSize( width
, height
);
752 #if wxUSE_MENUS_NATIVE
756 if (!m_menuBarDetached
)
757 (*height
) -= wxMENU_HEIGHT
;
759 (*height
) -= wxPLACE_HOLDER
;
761 #endif // wxUSE_MENUS_NATIVE
765 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) (*height
) -= wxSTATUS_HEIGHT
;
766 #endif // wxUSE_STATUSBAR
770 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
772 if (m_toolBarDetached
)
774 *height
-= wxPLACE_HOLDER
;
779 m_frameToolBar
->GetSize( &x
, &y
);
780 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
790 #endif // wxUSE_TOOLBAR
793 *height
-= m_miniEdge
*2 + m_miniTitle
;
797 *width
-= m_miniEdge
*2;
801 void wxFrameGTK::DoSetClientSize( int width
, int height
)
803 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
805 #if wxUSE_MENUS_NATIVE
809 if (!m_menuBarDetached
)
810 height
+= wxMENU_HEIGHT
;
812 height
+= wxPLACE_HOLDER
;
814 #endif // wxUSE_MENUS_NATIVE
818 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
823 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
825 if (m_toolBarDetached
)
827 height
+= wxPLACE_HOLDER
;
832 m_frameToolBar
->GetSize( &x
, &y
);
833 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
845 DoSetSize( -1, -1, width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0 );
848 void wxFrameGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
849 int width
, int height
)
851 // due to a bug in gtk, x,y are always 0
855 /* avoid recursions */
856 if (m_resizing
) return;
859 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
860 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
865 /* space occupied by m_frameToolBar and m_frameMenuBar */
866 int client_area_x_offset
= 0,
867 client_area_y_offset
= 0;
869 /* wxMDIChildFrame derives from wxFrameGTK but it _is_ a wxWindow as it uses
870 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
871 set in wxFrameGTK::Create so it is used to check what kind of frame we
872 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
873 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
874 importantly) m_mainWidget */
876 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
877 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
878 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
879 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
884 gint flag
= 0; // GDK_HINT_POS;
885 if ((m_minWidth
!= -1) || (m_minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
886 if ((m_maxWidth
!= -1) || (m_maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
888 geom
.min_width
= m_minWidth
;
889 geom
.min_height
= m_minHeight
;
890 geom
.max_width
= m_maxWidth
;
891 geom
.max_height
= m_maxHeight
;
892 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
895 (GdkWindowHints
) flag
);
897 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
898 * menubar, the toolbar and the client area, which is represented by
900 * this hurts in the eye, but I don't want to call SetSize()
901 * because I don't want to call any non-native functions here. */
903 #if wxUSE_MENUS_NATIVE
907 int yy
= m_miniEdge
+ m_miniTitle
;
908 int ww
= m_width
- 2*m_miniEdge
;
909 int hh
= wxMENU_HEIGHT
;
910 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
911 m_frameMenuBar
->m_x
= xx
;
912 m_frameMenuBar
->m_y
= yy
;
913 m_frameMenuBar
->m_width
= ww
;
914 m_frameMenuBar
->m_height
= hh
;
915 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
916 m_frameMenuBar
->m_widget
,
918 client_area_y_offset
+= hh
;
920 #endif // wxUSE_MENUS_NATIVE
923 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
924 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
927 int yy
= m_miniEdge
+ m_miniTitle
;
928 #if wxUSE_MENUS_NATIVE
931 if (!m_menuBarDetached
)
934 yy
+= wxPLACE_HOLDER
;
936 #endif // wxUSE_MENUS_NATIVE
938 m_frameToolBar
->m_x
= xx
;
939 m_frameToolBar
->m_y
= yy
;
941 /* don't change the toolbar's reported height/width */
943 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
945 ww
= m_toolBarDetached
? wxPLACE_HOLDER
946 : m_frameToolBar
->m_width
;
947 hh
= m_height
- 2*m_miniEdge
;
949 client_area_x_offset
+= ww
;
953 ww
= m_width
- 2*m_miniEdge
;
954 hh
= m_toolBarDetached
? wxPLACE_HOLDER
955 : m_frameToolBar
->m_height
;
957 client_area_y_offset
+= hh
;
960 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
961 m_frameToolBar
->m_widget
,
964 #endif // wxUSE_TOOLBAR
966 int client_x
= client_area_x_offset
+ m_miniEdge
;
967 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
968 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
969 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
970 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
972 client_x
, client_y
, client_w
, client_h
);
976 /* if there is no m_mainWidget between m_widget and m_wxwindow there
977 is no need to set the size or position of m_wxwindow. */
981 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
983 int xx
= 0 + m_miniEdge
;
984 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
985 int ww
= m_width
- 2*m_miniEdge
;
986 int hh
= wxSTATUS_HEIGHT
;
987 m_frameStatusBar
->m_x
= xx
;
988 m_frameStatusBar
->m_y
= yy
;
989 m_frameStatusBar
->m_width
= ww
;
990 m_frameStatusBar
->m_height
= hh
;
991 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
992 m_frameStatusBar
->m_widget
,
994 gtk_widget_draw( m_frameStatusBar
->m_widget
, (GdkRectangle
*) NULL
);
996 #endif // wxUSE_STATUSBAR
1000 // send size event to frame
1001 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1002 event
.SetEventObject( this );
1003 GetEventHandler()->ProcessEvent( event
);
1006 // send size event to status bar
1007 if (m_frameStatusBar
)
1009 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
1010 event2
.SetEventObject( m_frameStatusBar
);
1011 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
1013 #endif // wxUSE_STATUSBAR
1018 void wxFrameGTK::MakeModal( bool modal
)
1021 gtk_grab_add( m_widget
);
1023 gtk_grab_remove( m_widget
);
1026 void wxFrameGTK::OnInternalIdle()
1028 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1030 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1032 // we'll come back later
1034 wxapp_install_idle_handler();
1038 #if wxUSE_MENUS_NATIVE
1039 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
1040 #endif // wxUSE_MENUS_NATIVE
1042 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
1045 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
1048 wxWindow::OnInternalIdle();
1051 // ----------------------------------------------------------------------------
1052 // menu/tool/status bar stuff
1053 // ----------------------------------------------------------------------------
1055 #if wxUSE_MENUS_NATIVE
1057 void wxFrameGTK::DetachMenuBar()
1059 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1060 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
1062 if ( m_frameMenuBar
)
1064 m_frameMenuBar
->UnsetInvokingWindow( this );
1066 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1068 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1069 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1071 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1072 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1075 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
1076 gtk_widget_ref( m_frameMenuBar
->m_widget
);
1077 gtk_widget_unparent( m_frameMenuBar
->m_widget
);
1080 wxFrameBase::DetachMenuBar();
1083 void wxFrameGTK::AttachMenuBar( wxMenuBar
*menuBar
)
1085 wxFrameBase::AttachMenuBar(menuBar
);
1089 m_frameMenuBar
->SetInvokingWindow( this );
1091 m_frameMenuBar
->SetParent(this);
1092 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
1093 m_frameMenuBar
->m_widget
,
1094 m_frameMenuBar
->m_x
,
1095 m_frameMenuBar
->m_y
,
1096 m_frameMenuBar
->m_width
,
1097 m_frameMenuBar
->m_height
);
1099 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1101 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
1102 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1104 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
1105 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1108 m_frameMenuBar
->Show( TRUE
);
1111 /* resize window in OnInternalIdle */
1115 #endif // wxUSE_MENUS_NATIVE
1119 wxToolBar
* wxFrameGTK::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
1121 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1123 m_insertInClientArea
= FALSE
;
1125 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
1127 m_insertInClientArea
= TRUE
;
1131 return m_frameToolBar
;
1134 void wxFrameGTK::SetToolBar(wxToolBar
*toolbar
)
1136 wxFrameBase::SetToolBar(toolbar
);
1140 /* insert into toolbar area if not already there */
1141 if ((m_frameToolBar
->m_widget
->parent
) &&
1142 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
1144 GetChildren().DeleteObject( m_frameToolBar
);
1146 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
1152 #endif // wxUSE_TOOLBAR
1156 wxStatusBar
* wxFrameGTK::CreateStatusBar(int number
,
1159 const wxString
& name
)
1161 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1163 // because it will change when toolbar is added
1166 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
1169 void wxFrameGTK::PositionStatusBar()
1171 if ( !m_frameStatusBar
)
1176 #endif // wxUSE_STATUSBAR
1178 // ----------------------------------------------------------------------------
1180 // ----------------------------------------------------------------------------
1182 void wxFrameGTK::SetTitle( const wxString
&title
)
1184 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1187 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
1190 void wxFrameGTK::SetIcon( const wxIcon
&icon
)
1192 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1194 wxFrameBase::SetIcon(icon
);
1199 if (!m_widget
->window
)
1202 wxMask
*mask
= icon
.GetMask();
1203 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1204 if (mask
) bm
= mask
->GetBitmap();
1206 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1209 // ----------------------------------------------------------------------------
1210 // frame state: maximized/iconized/normal
1211 // ----------------------------------------------------------------------------
1213 void wxFrameGTK::Maximize(bool WXUNUSED(maximize
))
1215 wxFAIL_MSG( _T("not implemented") );
1218 bool wxFrameGTK::IsMaximized() const
1220 // wxFAIL_MSG( _T("not implemented") );
1222 // This is an approximation
1226 void wxFrameGTK::Restore()
1228 wxFAIL_MSG( _T("not implemented") );
1231 void wxFrameGTK::Iconize( bool iconize
)
1235 GdkWindow
*window
= m_widget
->window
;
1237 // you should do it later, for example from OnCreate() handler
1238 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1240 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1241 GDK_WINDOW_XWINDOW( window
),
1242 DefaultScreen( GDK_DISPLAY() ) );
1246 bool wxFrameGTK::IsIconized() const
1248 return m_isIconized
;
1251 void wxFrameGTK::SetIconizeState(bool iconize
)
1253 if ( iconize
!= m_isIconized
)
1255 m_isIconized
= iconize
;
1256 (void)SendIconizeEvent(iconize
);