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 #ifdef __WXUNIVERSAL__
68 IMPLEMENT_DYNAMIC_CLASS(wxFrameGTK
, wxWindow
)
70 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxWindow
)
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 extern wxList wxPendingDelete
;
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
85 extern void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
);
89 // ============================================================================
91 // ============================================================================
93 // ----------------------------------------------------------------------------
95 // ----------------------------------------------------------------------------
97 //-----------------------------------------------------------------------------
98 // "focus" from m_window
99 //-----------------------------------------------------------------------------
101 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
104 wxapp_install_idle_handler();
106 // This disables GTK's tab traversal
107 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
111 //-----------------------------------------------------------------------------
113 //-----------------------------------------------------------------------------
115 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxFrameGTK
*win
)
118 wxapp_install_idle_handler();
123 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
126 wxPrintf( "OnSize from " );
127 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
128 wxPrintf( win->GetClassInfo()->GetClassName() );
129 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
132 (int)alloc->height );
135 win
->m_width
= alloc
->width
;
136 win
->m_height
= alloc
->height
;
137 win
->m_queuedFullRedraw
= TRUE
;
138 win
->GtkUpdateSize();
142 //-----------------------------------------------------------------------------
144 //-----------------------------------------------------------------------------
146 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxFrameGTK
*win
)
149 wxapp_install_idle_handler();
151 if ((g_openDialogs
== 0) && (win
->IsEnabled()))
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();
181 #endif // wxUSE_MENUS
184 //-----------------------------------------------------------------------------
185 // "child_attached" of tool bar
186 //-----------------------------------------------------------------------------
188 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
190 if (!win
->m_hasVMT
) return;
192 win
->m_toolBarDetached
= FALSE
;
194 win
->GtkUpdateSize();
197 //-----------------------------------------------------------------------------
198 // "child_detached" of tool bar
199 //-----------------------------------------------------------------------------
201 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
204 wxapp_install_idle_handler();
206 if (!win
->m_hasVMT
) return;
208 win
->m_toolBarDetached
= TRUE
;
209 win
->GtkUpdateSize();
211 #endif // wxUSE_TOOLBAR
213 //-----------------------------------------------------------------------------
215 //-----------------------------------------------------------------------------
218 #if (GTK_MINOR_VERSION > 0)
219 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxFrameGTK
*win
)
221 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*event
, wxFrameGTK
*win
)
225 wxapp_install_idle_handler();
230 #if (GTK_MINOR_VERSION > 0)
233 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
241 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
242 mevent
.SetEventObject( win
);
243 win
->GetEventHandler()->ProcessEvent( mevent
);
248 //-----------------------------------------------------------------------------
249 // "realize" from m_widget
250 //-----------------------------------------------------------------------------
252 /* we cannot MWM hints and icons before the widget has been realized,
253 so we do this directly after realization */
256 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
), wxFrameGTK
*win
)
259 wxapp_install_idle_handler();
261 if ((win
->m_miniEdge
> 0) || (win
->HasFlag(wxSIMPLE_BORDER
)) || (win
->HasFlag(wxNO_BORDER
)))
263 /* This is a mini-frame or a borderless frame. */
264 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)0 );
265 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)0 );
269 /* All this is for Motif Window Manager "hints" and is supposed to be
270 recognized by other WM as well. Not tested. */
271 long decor
= (long) GDK_DECOR_BORDER
;
272 long func
= (long) GDK_FUNC_MOVE
;
274 if ((win
->GetWindowStyle() & wxCAPTION
) != 0)
275 decor
|= GDK_DECOR_TITLE
;
276 if ((win
->GetWindowStyle() & wxSYSTEM_MENU
) != 0)
278 decor
|= GDK_DECOR_MENU
;
279 func
|= GDK_FUNC_CLOSE
;
281 if ((win
->GetWindowStyle() & wxMINIMIZE_BOX
) != 0)
283 func
|= GDK_FUNC_MINIMIZE
;
284 decor
|= GDK_DECOR_MINIMIZE
;
286 if ((win
->GetWindowStyle() & wxMAXIMIZE_BOX
) != 0)
288 func
|= GDK_FUNC_MAXIMIZE
;
289 decor
|= GDK_DECOR_MAXIMIZE
;
291 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) != 0)
293 func
|= GDK_FUNC_RESIZE
;
294 decor
|= GDK_DECOR_RESIZEH
;
297 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)decor
);
298 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)func
);
301 /* GTK's shrinking/growing policy */
302 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) == 0)
303 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
305 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
308 wxIcon iconOld
= win
->GetIcon();
309 if ( iconOld
!= wxNullIcon
)
311 wxIcon
icon( iconOld
);
312 win
->SetIcon( wxNullIcon
);
313 win
->SetIcon( icon
);
316 /* we set the focus to the child that accepts the focus. this
317 doesn't really have to be done in "realize" but why not? */
318 wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
321 wxWindow
*child
= node
->GetData();
322 if (child
->AcceptsFocus())
328 node
= node
->GetNext();
332 //-----------------------------------------------------------------------------
333 // "map_event" from m_widget
334 //-----------------------------------------------------------------------------
337 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
338 GdkEvent
* WXUNUSED(event
),
341 win
->SetIconizeState(FALSE
);
344 //-----------------------------------------------------------------------------
345 // "unmap_event" from m_widget
346 //-----------------------------------------------------------------------------
349 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
350 GdkEvent
* WXUNUSED(event
),
353 win
->SetIconizeState(TRUE
);
356 //-----------------------------------------------------------------------------
357 // "expose_event" of m_client
358 //-----------------------------------------------------------------------------
360 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
362 GtkPizza
*pizza
= GTK_PIZZA(widget
);
364 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
365 GTK_SHADOW_NONE
, &gdk_event
->area
, win
->m_widget
, "base", 0, 0, -1, -1);
370 //-----------------------------------------------------------------------------
371 // "draw" of m_client
372 //-----------------------------------------------------------------------------
375 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
377 GtkPizza
*pizza
= GTK_PIZZA(widget
);
379 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
380 GTK_SHADOW_NONE
, rect
, win
->m_widget
, "base", 0, 0, -1, -1);
383 // ----------------------------------------------------------------------------
385 // ----------------------------------------------------------------------------
387 //-----------------------------------------------------------------------------
388 // InsertChild for wxFrameGTK
389 //-----------------------------------------------------------------------------
391 /* Callback for wxFrameGTK. This very strange beast has to be used because
392 * C++ has no virtual methods in a constructor. We have to emulate a
393 * virtual function here as wxWindows requires different ways to insert
394 * a child in container classes. */
396 static void wxInsertChildInFrame( wxFrameGTK
* parent
, wxWindow
* child
)
398 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
400 if (!parent
->m_insertInClientArea
)
402 /* these are outside the client area */
403 wxFrameGTK
* frame
= (wxFrameGTK
*) parent
;
404 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
405 GTK_WIDGET(child
->m_widget
),
411 #if wxUSE_TOOLBAR_NATIVE
412 /* we connect to these events for recalculating the client area
413 space when the toolbar is floating */
414 if (wxIS_KIND_OF(child
,wxToolBar
))
416 wxToolBar
*toolBar
= (wxToolBar
*) child
;
417 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
419 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
420 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
422 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
423 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
426 #endif // wxUSE_TOOLBAR
430 /* these are inside the client area */
431 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
432 GTK_WIDGET(child
->m_widget
),
439 /* resize on OnInternalIdle */
440 parent
->GtkUpdateSize();
443 // ----------------------------------------------------------------------------
444 // wxFrameGTK creation
445 // ----------------------------------------------------------------------------
447 void wxFrameGTK::Init()
452 m_mainWidget
= (GtkWidget
*) NULL
;
453 m_menuBarDetached
= FALSE
;
454 m_toolBarDetached
= FALSE
;
455 m_insertInClientArea
= TRUE
;
457 m_isIconized
= FALSE
;
458 m_fsIsShowing
= FALSE
;
459 m_themeEnabled
= TRUE
;
462 bool wxFrameGTK::Create( wxWindow
*parent
,
464 const wxString
& title
,
466 const wxSize
& sizeOrig
,
468 const wxString
&name
)
470 // always create a frame of some reasonable, even if arbitrary, size (at
471 // least for MSW compatibility)
472 wxSize size
= sizeOrig
;
473 if ( size
.x
== -1 || size
.y
== -1 )
475 wxSize sizeDpy
= wxGetDisplaySize();
477 size
.x
= sizeDpy
.x
/ 3;
479 size
.y
= sizeDpy
.y
/ 5;
482 wxTopLevelWindows
.Append( this );
484 m_needParent
= FALSE
;
486 if (!PreCreation( parent
, pos
, size
) ||
487 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
489 wxFAIL_MSG( wxT("wxFrameGTK creation failed") );
495 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
497 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
499 if (style
& wxFRAME_TOOL_WINDOW
)
500 win_type
= GTK_WINDOW_POPUP
;
502 m_widget
= gtk_window_new( win_type
);
504 if ((m_parent
) && (HasFlag(wxFRAME_FLOAT_ON_PARENT
)) && (GTK_IS_WINDOW(m_parent
->m_widget
)))
505 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
508 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), name
.mb_str(), name
.mb_str() );
511 debug_focus_in( m_widget
, wxT("wxFrameGTK::m_widget"), name
);
514 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
515 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
517 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
518 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
520 /* m_mainWidget holds the toolbar, the menubar and the client area */
521 m_mainWidget
= gtk_pizza_new();
522 gtk_widget_show( m_mainWidget
);
523 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
524 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
526 /* for m_mainWidget themes */
527 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
528 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
529 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
530 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
533 debug_focus_in( m_mainWidget
, wxT("wxFrameGTK::m_mainWidget"), name
);
536 /* m_wxwindow only represents the client area without toolbar and menubar */
537 m_wxwindow
= gtk_pizza_new();
538 gtk_widget_show( m_wxwindow
);
539 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
542 debug_focus_in( m_wxwindow
, wxT("wxFrameGTK::m_wxwindow"), name
);
545 /* we donm't allow the frame to get the focus as otherwise
546 the frame will grab it at arbitrary focus changes. */
547 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
549 if (m_parent
) m_parent
->AddChild( this );
551 /* the user resized the frame by dragging etc. */
552 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
553 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
557 if ((m_x
!= -1) || (m_y
!= -1))
558 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
559 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
561 /* we cannot set MWM hints and icons before the widget has
562 been realized, so we do this directly after realization */
563 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
564 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
566 /* the only way to get the window size is to connect to this event */
567 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
568 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
570 /* map and unmap for iconized state */
571 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
572 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
573 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
574 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
576 /* the only way to get the window size is to connect to this event */
577 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
578 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
580 /* disable native tab traversal */
581 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
582 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
587 wxFrameGTK::~wxFrameGTK()
589 m_isBeingDeleted
= TRUE
;
593 wxTopLevelWindows
.DeleteObject( this );
595 if (wxTheApp
->GetTopWindow() == this)
596 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
598 if ((wxTopLevelWindows
.Number() == 0) &&
599 (wxTheApp
->GetExitOnFrameDelete()))
601 wxTheApp
->ExitMainLoop();
605 bool wxFrame::ShowFullScreen(bool show
, long style
)
607 if (show
== m_fsIsShowing
) return FALSE
; // return what?
609 m_fsIsShowing
= show
;
613 m_fsSaveStyle
= m_windowStyle
;
614 m_fsSaveFlag
= style
;
615 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
616 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
618 gtk_widget_hide( m_widget
);
619 gtk_widget_unrealize( m_widget
);
621 m_windowStyle
= wxSIMPLE_BORDER
;
625 wxDisplaySize( &x
, &y
);
626 SetSize( 0, 0, x
, y
);
628 gtk_widget_realize( m_widget
);
629 gtk_widget_show( m_widget
);
633 gtk_widget_hide( m_widget
);
634 gtk_widget_unrealize( m_widget
);
636 m_windowStyle
= m_fsSaveStyle
;
638 SetSize( m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
640 gtk_widget_realize( m_widget
);
641 gtk_widget_show( m_widget
);
647 // ----------------------------------------------------------------------------
648 // overridden wxWindow methods
649 // ----------------------------------------------------------------------------
651 bool wxFrameGTK::Show( bool show
)
653 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
655 if (show
&& !m_sizeSet
)
657 /* by calling GtkOnSize here, we don't have to call
658 either after showing the frame, which would entail
659 much ugly flicker or from within the size_allocate
660 handler, because GTK 1.1.X forbids that. */
662 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
665 return wxWindow::Show( show
);
668 void wxFrameGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
670 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrameGTK") );
673 void wxFrameGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
675 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
677 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
678 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
680 /* avoid recursions */
688 int old_width
= m_width
;
689 int old_height
= m_height
;
691 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
693 if (x
!= -1) m_x
= x
;
694 if (y
!= -1) m_y
= y
;
695 if (width
!= -1) m_width
= width
;
696 if (height
!= -1) m_height
= height
;
707 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
709 if (width == -1) m_width = 80;
712 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
714 if (height == -1) m_height = 26;
718 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
719 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
720 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
721 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
723 if ((m_x
!= -1) || (m_y
!= -1))
725 if ((m_x
!= old_x
) || (m_y
!= old_y
))
727 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
731 if ((m_width
!= old_width
) || (m_height
!= old_height
))
733 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
735 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
736 done either directly before the frame is shown or in idle time
737 so that different calls to SetSize() don't lead to flicker. */
744 void wxFrameGTK::DoGetClientSize( int *width
, int *height
) const
746 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
748 wxWindow::DoGetClientSize( width
, height
);
755 if (!m_menuBarDetached
)
756 (*height
) -= wxMENU_HEIGHT
;
758 (*height
) -= wxPLACE_HOLDER
;
760 #endif // wxUSE_MENUS
764 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) (*height
) -= wxSTATUS_HEIGHT
;
765 #endif // wxUSE_STATUSBAR
769 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
771 if (m_toolBarDetached
)
773 *height
-= wxPLACE_HOLDER
;
778 m_frameToolBar
->GetSize( &x
, &y
);
779 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
789 #endif // wxUSE_TOOLBAR
792 *height
-= m_miniEdge
*2 + m_miniTitle
;
796 *width
-= m_miniEdge
*2;
800 void wxFrameGTK::DoSetClientSize( int width
, int height
)
802 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
808 if (!m_menuBarDetached
)
809 height
+= wxMENU_HEIGHT
;
811 height
+= wxPLACE_HOLDER
;
813 #endif // wxUSE_MENUS
817 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
822 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
824 if (m_toolBarDetached
)
826 height
+= wxPLACE_HOLDER
;
831 m_frameToolBar
->GetSize( &x
, &y
);
832 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
844 DoSetSize( -1, -1, width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0 );
847 void wxFrameGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
848 int width
, int height
)
850 // due to a bug in gtk, x,y are always 0
854 /* avoid recursions */
855 if (m_resizing
) return;
858 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
859 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
864 /* space occupied by m_frameToolBar and m_frameMenuBar */
865 int client_area_x_offset
= 0,
866 client_area_y_offset
= 0;
868 /* wxMDIChildFrame derives from wxFrameGTK but it _is_ a wxWindow as it uses
869 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
870 set in wxFrameGTK::Create so it is used to check what kind of frame we
871 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
872 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
873 importantly) m_mainWidget */
875 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
876 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
877 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
878 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
883 gint flag
= 0; // GDK_HINT_POS;
884 if ((m_minWidth
!= -1) || (m_minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
885 if ((m_maxWidth
!= -1) || (m_maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
887 geom
.min_width
= m_minWidth
;
888 geom
.min_height
= m_minHeight
;
889 geom
.max_width
= m_maxWidth
;
890 geom
.max_height
= m_maxHeight
;
891 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
894 (GdkWindowHints
) flag
);
896 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
897 * menubar, the toolbar and the client area, which is represented by
899 * this hurts in the eye, but I don't want to call SetSize()
900 * because I don't want to call any non-native functions here. */
906 int yy
= m_miniEdge
+ m_miniTitle
;
907 int ww
= m_width
- 2*m_miniEdge
;
908 int hh
= wxMENU_HEIGHT
;
909 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
910 m_frameMenuBar
->m_x
= xx
;
911 m_frameMenuBar
->m_y
= yy
;
912 m_frameMenuBar
->m_width
= ww
;
913 m_frameMenuBar
->m_height
= hh
;
914 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
915 m_frameMenuBar
->m_widget
,
917 client_area_y_offset
+= hh
;
919 #endif // wxUSE_MENUS
922 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
923 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
926 int yy
= m_miniEdge
+ m_miniTitle
;
930 if (!m_menuBarDetached
)
933 yy
+= wxPLACE_HOLDER
;
935 #endif // wxUSE_MENUS
937 m_frameToolBar
->m_x
= xx
;
938 m_frameToolBar
->m_y
= yy
;
940 /* don't change the toolbar's reported height/width */
942 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
944 ww
= m_toolBarDetached
? wxPLACE_HOLDER
945 : m_frameToolBar
->m_width
;
946 hh
= m_height
- 2*m_miniEdge
;
948 client_area_x_offset
+= ww
;
952 ww
= m_width
- 2*m_miniEdge
;
953 hh
= m_toolBarDetached
? wxPLACE_HOLDER
954 : m_frameToolBar
->m_height
;
956 client_area_y_offset
+= hh
;
959 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
960 m_frameToolBar
->m_widget
,
963 #endif // wxUSE_TOOLBAR
965 int client_x
= client_area_x_offset
+ m_miniEdge
;
966 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
967 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
968 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
969 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
971 client_x
, client_y
, client_w
, client_h
);
975 /* if there is no m_mainWidget between m_widget and m_wxwindow there
976 is no need to set the size or position of m_wxwindow. */
980 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
982 int xx
= 0 + m_miniEdge
;
983 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
984 int ww
= m_width
- 2*m_miniEdge
;
985 int hh
= wxSTATUS_HEIGHT
;
986 m_frameStatusBar
->m_x
= xx
;
987 m_frameStatusBar
->m_y
= yy
;
988 m_frameStatusBar
->m_width
= ww
;
989 m_frameStatusBar
->m_height
= hh
;
990 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
991 m_frameStatusBar
->m_widget
,
993 gtk_widget_draw( m_frameStatusBar
->m_widget
, (GdkRectangle
*) NULL
);
995 #endif // wxUSE_STATUSBAR
999 // send size event to frame
1000 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1001 event
.SetEventObject( this );
1002 GetEventHandler()->ProcessEvent( event
);
1005 // send size event to status bar
1006 if (m_frameStatusBar
)
1008 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
1009 event2
.SetEventObject( m_frameStatusBar
);
1010 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
1012 #endif // wxUSE_STATUSBAR
1017 void wxFrameGTK::MakeModal( bool modal
)
1020 gtk_grab_add( m_widget
);
1022 gtk_grab_remove( m_widget
);
1025 void wxFrameGTK::OnInternalIdle()
1027 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1029 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1031 // we'll come back later
1033 wxapp_install_idle_handler();
1038 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
1039 #endif // wxUSE_MENUS
1041 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
1044 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
1047 wxWindow::OnInternalIdle();
1050 // ----------------------------------------------------------------------------
1051 // menu/tool/status bar stuff
1052 // ----------------------------------------------------------------------------
1056 void wxFrameGTK::SetMenuBar( wxMenuBar
*menuBar
)
1058 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1059 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
1061 if (menuBar
== m_frameMenuBar
)
1066 m_frameMenuBar
->UnsetInvokingWindow( this );
1068 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1070 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1071 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1073 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1074 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1077 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
1078 gtk_widget_ref( m_frameMenuBar
->m_widget
);
1079 gtk_widget_unparent( m_frameMenuBar
->m_widget
);
1082 m_frameMenuBar
= menuBar
;
1086 m_frameMenuBar
->SetInvokingWindow( this );
1088 m_frameMenuBar
->SetParent(this);
1089 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
1090 m_frameMenuBar
->m_widget
,
1091 m_frameMenuBar
->m_x
,
1092 m_frameMenuBar
->m_y
,
1093 m_frameMenuBar
->m_width
,
1094 m_frameMenuBar
->m_height
);
1096 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1098 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
1099 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1101 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
1102 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1105 m_frameMenuBar
->Show( TRUE
);
1108 /* resize window in OnInternalIdle */
1112 #endif // wxUSE_MENUS
1116 wxToolBar
* wxFrameGTK::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
1118 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1120 m_insertInClientArea
= FALSE
;
1122 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
1124 m_insertInClientArea
= TRUE
;
1128 return m_frameToolBar
;
1131 void wxFrameGTK::SetToolBar(wxToolBar
*toolbar
)
1133 wxFrameBase::SetToolBar(toolbar
);
1137 /* insert into toolbar area if not already there */
1138 if ((m_frameToolBar
->m_widget
->parent
) &&
1139 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
1141 GetChildren().DeleteObject( m_frameToolBar
);
1143 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
1149 #endif // wxUSE_TOOLBAR
1153 wxStatusBar
* wxFrameGTK::CreateStatusBar(int number
,
1156 const wxString
& name
)
1158 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1160 // because it will change when toolbar is added
1163 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
1166 void wxFrameGTK::PositionStatusBar()
1168 if ( !m_frameStatusBar
)
1173 #endif // wxUSE_STATUSBAR
1175 // ----------------------------------------------------------------------------
1177 // ----------------------------------------------------------------------------
1179 void wxFrameGTK::SetTitle( const wxString
&title
)
1181 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1184 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
1187 void wxFrameGTK::SetIcon( const wxIcon
&icon
)
1189 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1191 wxFrameBase::SetIcon(icon
);
1196 if (!m_widget
->window
)
1199 wxMask
*mask
= icon
.GetMask();
1200 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1201 if (mask
) bm
= mask
->GetBitmap();
1203 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1206 // ----------------------------------------------------------------------------
1207 // frame state: maximized/iconized/normal
1208 // ----------------------------------------------------------------------------
1210 void wxFrameGTK::Maximize(bool WXUNUSED(maximize
))
1212 wxFAIL_MSG( _T("not implemented") );
1215 bool wxFrameGTK::IsMaximized() const
1217 // wxFAIL_MSG( _T("not implemented") );
1219 // This is an approximation
1223 void wxFrameGTK::Restore()
1225 wxFAIL_MSG( _T("not implemented") );
1228 void wxFrameGTK::Iconize( bool iconize
)
1232 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget
->window
),
1233 GDK_WINDOW_XWINDOW( m_widget
->window
),
1234 DefaultScreen( GDK_DISPLAY() ) );
1238 bool wxFrameGTK::IsIconized() const
1240 return m_isIconized
;
1243 void wxFrame::SetIconizeState(bool iconize
)
1245 if ( iconize
!= m_isIconized
)
1247 m_isIconized
= iconize
;
1248 (void)SendIconizeEvent(iconize
);
1252 // this is not supposed to happen if we're called only from
1253 // gtk_frame_(un)map_callback!
1255 // RR: I don't understand this test. Upon startup, the frame is
1256 // not iconized by default, it has just not been created
1258 ///wxFAIL_MSG( _T("unexpected call to SendIconizeEvent ignored") );