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()))
157 //-----------------------------------------------------------------------------
158 // "child_attached" of menu bar
159 //-----------------------------------------------------------------------------
161 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
163 if (!win
->m_hasVMT
) return;
165 win
->m_menuBarDetached
= FALSE
;
166 win
->GtkUpdateSize();
169 //-----------------------------------------------------------------------------
170 // "child_detached" of menu bar
171 //-----------------------------------------------------------------------------
173 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
175 if (!win
->m_hasVMT
) return;
177 win
->m_menuBarDetached
= TRUE
;
178 win
->GtkUpdateSize();
180 #endif // wxUSE_MENUS
183 //-----------------------------------------------------------------------------
184 // "child_attached" of tool bar
185 //-----------------------------------------------------------------------------
187 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
189 if (!win
->m_hasVMT
) return;
191 win
->m_toolBarDetached
= FALSE
;
193 win
->GtkUpdateSize();
196 //-----------------------------------------------------------------------------
197 // "child_detached" of tool bar
198 //-----------------------------------------------------------------------------
200 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
203 wxapp_install_idle_handler();
205 if (!win
->m_hasVMT
) return;
207 win
->m_toolBarDetached
= TRUE
;
208 win
->GtkUpdateSize();
210 #endif // wxUSE_TOOLBAR
212 //-----------------------------------------------------------------------------
214 //-----------------------------------------------------------------------------
217 #if (GTK_MINOR_VERSION > 0)
218 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxFrameGTK
*win
)
220 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*event
, wxFrameGTK
*win
)
224 wxapp_install_idle_handler();
229 #if (GTK_MINOR_VERSION > 0)
232 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
240 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
241 mevent
.SetEventObject( win
);
242 win
->GetEventHandler()->ProcessEvent( mevent
);
247 //-----------------------------------------------------------------------------
248 // "realize" from m_widget
249 //-----------------------------------------------------------------------------
251 /* we cannot MWM hints and icons before the widget has been realized,
252 so we do this directly after realization */
255 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
), wxFrameGTK
*win
)
258 wxapp_install_idle_handler();
260 if ((win
->m_miniEdge
> 0) || (win
->HasFlag(wxSIMPLE_BORDER
)) || (win
->HasFlag(wxNO_BORDER
)))
262 /* This is a mini-frame or a borderless frame. */
263 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)0 );
264 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)0 );
268 /* All this is for Motif Window Manager "hints" and is supposed to be
269 recognized by other WM as well. Not tested. */
270 long decor
= (long) GDK_DECOR_BORDER
;
271 long func
= (long) GDK_FUNC_MOVE
;
273 if ((win
->GetWindowStyle() & wxCAPTION
) != 0)
274 decor
|= GDK_DECOR_TITLE
;
275 if ((win
->GetWindowStyle() & wxSYSTEM_MENU
) != 0)
277 decor
|= GDK_DECOR_MENU
;
278 func
|= GDK_FUNC_CLOSE
;
280 if ((win
->GetWindowStyle() & wxMINIMIZE_BOX
) != 0)
282 func
|= GDK_FUNC_MINIMIZE
;
283 decor
|= GDK_DECOR_MINIMIZE
;
285 if ((win
->GetWindowStyle() & wxMAXIMIZE_BOX
) != 0)
287 func
|= GDK_FUNC_MAXIMIZE
;
288 decor
|= GDK_DECOR_MAXIMIZE
;
290 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) != 0)
292 func
|= GDK_FUNC_RESIZE
;
293 decor
|= GDK_DECOR_RESIZEH
;
296 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)decor
);
297 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)func
);
300 /* GTK's shrinking/growing policy */
301 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) == 0)
302 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
304 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
307 wxIcon iconOld
= win
->GetIcon();
308 if ( iconOld
!= wxNullIcon
)
310 wxIcon
icon( iconOld
);
311 win
->SetIcon( wxNullIcon
);
312 win
->SetIcon( icon
);
315 /* we set the focus to the child that accepts the focus. this
316 doesn't really have to be done in "realize" but why not? */
317 wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
320 wxWindow
*child
= node
->GetData();
321 if (child
->AcceptsFocus())
327 node
= node
->GetNext();
331 //-----------------------------------------------------------------------------
332 // "map_event" from m_widget
333 //-----------------------------------------------------------------------------
336 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
337 GdkEvent
* WXUNUSED(event
),
340 win
->SetIconizeState(FALSE
);
343 //-----------------------------------------------------------------------------
344 // "unmap_event" from m_widget
345 //-----------------------------------------------------------------------------
348 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
349 GdkEvent
* WXUNUSED(event
),
352 win
->SetIconizeState(TRUE
);
355 //-----------------------------------------------------------------------------
356 // "expose_event" of m_client
357 //-----------------------------------------------------------------------------
359 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
361 GtkPizza
*pizza
= GTK_PIZZA(widget
);
363 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
364 GTK_SHADOW_NONE
, &gdk_event
->area
, win
->m_widget
, "base", 0, 0, -1, -1);
369 //-----------------------------------------------------------------------------
370 // "draw" of m_client
371 //-----------------------------------------------------------------------------
374 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
376 GtkPizza
*pizza
= GTK_PIZZA(widget
);
378 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
379 GTK_SHADOW_NONE
, rect
, win
->m_widget
, "base", 0, 0, -1, -1);
382 // ----------------------------------------------------------------------------
384 // ----------------------------------------------------------------------------
386 //-----------------------------------------------------------------------------
387 // InsertChild for wxFrameGTK
388 //-----------------------------------------------------------------------------
390 /* Callback for wxFrameGTK. This very strange beast has to be used because
391 * C++ has no virtual methods in a constructor. We have to emulate a
392 * virtual function here as wxWindows requires different ways to insert
393 * a child in container classes. */
395 static void wxInsertChildInFrame( wxFrameGTK
* parent
, wxWindow
* child
)
397 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
399 if (!parent
->m_insertInClientArea
)
401 /* these are outside the client area */
402 wxFrameGTK
* frame
= (wxFrameGTK
*) parent
;
403 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
404 GTK_WIDGET(child
->m_widget
),
410 #if wxUSE_TOOLBAR_NATIVE
411 /* we connect to these events for recalculating the client area
412 space when the toolbar is floating */
413 if (wxIS_KIND_OF(child
,wxToolBar
))
415 wxToolBar
*toolBar
= (wxToolBar
*) child
;
416 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
418 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
419 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
421 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
422 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
425 #endif // wxUSE_TOOLBAR
429 /* these are inside the client area */
430 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
431 GTK_WIDGET(child
->m_widget
),
438 /* resize on OnInternalIdle */
439 parent
->GtkUpdateSize();
442 // ----------------------------------------------------------------------------
443 // wxFrameGTK creation
444 // ----------------------------------------------------------------------------
446 void wxFrameGTK::Init()
451 m_mainWidget
= (GtkWidget
*) NULL
;
452 m_menuBarDetached
= FALSE
;
453 m_toolBarDetached
= FALSE
;
454 m_insertInClientArea
= TRUE
;
456 m_isIconized
= FALSE
;
457 m_fsIsShowing
= FALSE
;
458 m_themeEnabled
= TRUE
;
461 bool wxFrameGTK::Create( wxWindow
*parent
,
463 const wxString
& title
,
465 const wxSize
& sizeOrig
,
467 const wxString
&name
)
469 // always create a frame of some reasonable, even if arbitrary, size (at
470 // least for MSW compatibility)
471 wxSize size
= sizeOrig
;
472 if ( size
.x
== -1 || size
.y
== -1 )
474 wxSize sizeDpy
= wxGetDisplaySize();
476 size
.x
= sizeDpy
.x
/ 3;
478 size
.y
= sizeDpy
.y
/ 5;
481 wxTopLevelWindows
.Append( this );
483 m_needParent
= FALSE
;
485 if (!PreCreation( parent
, pos
, size
) ||
486 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
488 wxFAIL_MSG( wxT("wxFrameGTK creation failed") );
494 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
496 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
498 if (style
& wxFRAME_TOOL_WINDOW
)
499 win_type
= GTK_WINDOW_POPUP
;
501 m_widget
= gtk_window_new( win_type
);
503 if ((m_parent
) && (HasFlag(wxFRAME_FLOAT_ON_PARENT
)) && (GTK_IS_WINDOW(m_parent
->m_widget
)))
504 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
507 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), name
.mb_str(), name
.mb_str() );
510 debug_focus_in( m_widget
, wxT("wxFrameGTK::m_widget"), name
);
513 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
514 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
516 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
517 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
519 /* m_mainWidget holds the toolbar, the menubar and the client area */
520 m_mainWidget
= gtk_pizza_new();
521 gtk_widget_show( m_mainWidget
);
522 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
523 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
525 /* for m_mainWidget themes */
526 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
527 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
528 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
529 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
532 debug_focus_in( m_mainWidget
, wxT("wxFrameGTK::m_mainWidget"), name
);
535 /* m_wxwindow only represents the client area without toolbar and menubar */
536 m_wxwindow
= gtk_pizza_new();
537 gtk_widget_show( m_wxwindow
);
538 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
541 debug_focus_in( m_wxwindow
, wxT("wxFrameGTK::m_wxwindow"), name
);
544 /* we donm't allow the frame to get the focus as otherwise
545 the frame will grab it at arbitrary focus changes. */
546 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
548 if (m_parent
) m_parent
->AddChild( this );
550 /* the user resized the frame by dragging etc. */
551 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
552 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
556 if ((m_x
!= -1) || (m_y
!= -1))
557 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
558 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
560 /* we cannot set MWM hints and icons before the widget has
561 been realized, so we do this directly after realization */
562 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
563 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
565 /* the only way to get the window size is to connect to this event */
566 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
567 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
569 /* map and unmap for iconized state */
570 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
571 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
572 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
573 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
575 /* the only way to get the window size is to connect to this event */
576 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
577 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
579 /* disable native tab traversal */
580 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
581 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
586 wxFrameGTK::~wxFrameGTK()
588 m_isBeingDeleted
= TRUE
;
592 wxTopLevelWindows
.DeleteObject( this );
594 if (wxTheApp
->GetTopWindow() == this)
595 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
597 if ((wxTopLevelWindows
.Number() == 0) &&
598 (wxTheApp
->GetExitOnFrameDelete()))
600 wxTheApp
->ExitMainLoop();
604 bool wxFrameGTK::ShowFullScreen(bool show
, long style
)
606 if (show
== m_fsIsShowing
) return FALSE
; // return what?
608 m_fsIsShowing
= show
;
612 m_fsSaveStyle
= m_windowStyle
;
613 m_fsSaveFlag
= style
;
614 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
615 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
617 gtk_widget_hide( m_widget
);
618 gtk_widget_unrealize( m_widget
);
620 m_windowStyle
= wxSIMPLE_BORDER
;
624 wxDisplaySize( &x
, &y
);
625 SetSize( 0, 0, x
, y
);
627 gtk_widget_realize( m_widget
);
628 gtk_widget_show( m_widget
);
632 gtk_widget_hide( m_widget
);
633 gtk_widget_unrealize( m_widget
);
635 m_windowStyle
= m_fsSaveStyle
;
637 SetSize( m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
639 gtk_widget_realize( m_widget
);
640 gtk_widget_show( m_widget
);
646 // ----------------------------------------------------------------------------
647 // overridden wxWindow methods
648 // ----------------------------------------------------------------------------
650 bool wxFrameGTK::Show( bool show
)
652 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
654 if (show
&& !m_sizeSet
)
656 /* by calling GtkOnSize here, we don't have to call
657 either after showing the frame, which would entail
658 much ugly flicker or from within the size_allocate
659 handler, because GTK 1.1.X forbids that. */
661 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
664 return wxWindow::Show( show
);
667 void wxFrameGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
669 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrameGTK") );
672 void wxFrameGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
674 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
676 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
677 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
679 /* avoid recursions */
687 int old_width
= m_width
;
688 int old_height
= m_height
;
690 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
692 if (x
!= -1) m_x
= x
;
693 if (y
!= -1) m_y
= y
;
694 if (width
!= -1) m_width
= width
;
695 if (height
!= -1) m_height
= height
;
706 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
708 if (width == -1) m_width = 80;
711 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
713 if (height == -1) m_height = 26;
717 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
718 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
719 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
720 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
722 if ((m_x
!= -1) || (m_y
!= -1))
724 if ((m_x
!= old_x
) || (m_y
!= old_y
))
726 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
730 if ((m_width
!= old_width
) || (m_height
!= old_height
))
732 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
734 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
735 done either directly before the frame is shown or in idle time
736 so that different calls to SetSize() don't lead to flicker. */
743 void wxFrameGTK::DoGetClientSize( int *width
, int *height
) const
745 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
747 wxWindow::DoGetClientSize( width
, height
);
754 if (!m_menuBarDetached
)
755 (*height
) -= wxMENU_HEIGHT
;
757 (*height
) -= wxPLACE_HOLDER
;
759 #endif // wxUSE_MENUS
763 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) (*height
) -= wxSTATUS_HEIGHT
;
764 #endif // wxUSE_STATUSBAR
768 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
770 if (m_toolBarDetached
)
772 *height
-= wxPLACE_HOLDER
;
777 m_frameToolBar
->GetSize( &x
, &y
);
778 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
788 #endif // wxUSE_TOOLBAR
791 *height
-= m_miniEdge
*2 + m_miniTitle
;
795 *width
-= m_miniEdge
*2;
799 void wxFrameGTK::DoSetClientSize( int width
, int height
)
801 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
807 if (!m_menuBarDetached
)
808 height
+= wxMENU_HEIGHT
;
810 height
+= wxPLACE_HOLDER
;
812 #endif // wxUSE_MENUS
816 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
821 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
823 if (m_toolBarDetached
)
825 height
+= wxPLACE_HOLDER
;
830 m_frameToolBar
->GetSize( &x
, &y
);
831 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
843 DoSetSize( -1, -1, width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0 );
846 void wxFrameGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
847 int width
, int height
)
849 // due to a bug in gtk, x,y are always 0
853 /* avoid recursions */
854 if (m_resizing
) return;
857 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
858 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
863 /* space occupied by m_frameToolBar and m_frameMenuBar */
864 int client_area_x_offset
= 0,
865 client_area_y_offset
= 0;
867 /* wxMDIChildFrame derives from wxFrameGTK but it _is_ a wxWindow as it uses
868 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
869 set in wxFrameGTK::Create so it is used to check what kind of frame we
870 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
871 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
872 importantly) m_mainWidget */
874 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
875 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
876 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
877 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
882 gint flag
= 0; // GDK_HINT_POS;
883 if ((m_minWidth
!= -1) || (m_minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
884 if ((m_maxWidth
!= -1) || (m_maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
886 geom
.min_width
= m_minWidth
;
887 geom
.min_height
= m_minHeight
;
888 geom
.max_width
= m_maxWidth
;
889 geom
.max_height
= m_maxHeight
;
890 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
893 (GdkWindowHints
) flag
);
895 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
896 * menubar, the toolbar and the client area, which is represented by
898 * this hurts in the eye, but I don't want to call SetSize()
899 * because I don't want to call any non-native functions here. */
905 int yy
= m_miniEdge
+ m_miniTitle
;
906 int ww
= m_width
- 2*m_miniEdge
;
907 int hh
= wxMENU_HEIGHT
;
908 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
909 m_frameMenuBar
->m_x
= xx
;
910 m_frameMenuBar
->m_y
= yy
;
911 m_frameMenuBar
->m_width
= ww
;
912 m_frameMenuBar
->m_height
= hh
;
913 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
914 m_frameMenuBar
->m_widget
,
916 client_area_y_offset
+= hh
;
918 #endif // wxUSE_MENUS
921 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
922 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
925 int yy
= m_miniEdge
+ m_miniTitle
;
929 if (!m_menuBarDetached
)
932 yy
+= wxPLACE_HOLDER
;
934 #endif // wxUSE_MENUS
936 m_frameToolBar
->m_x
= xx
;
937 m_frameToolBar
->m_y
= yy
;
939 /* don't change the toolbar's reported height/width */
941 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
943 ww
= m_toolBarDetached
? wxPLACE_HOLDER
944 : m_frameToolBar
->m_width
;
945 hh
= m_height
- 2*m_miniEdge
;
947 client_area_x_offset
+= ww
;
951 ww
= m_width
- 2*m_miniEdge
;
952 hh
= m_toolBarDetached
? wxPLACE_HOLDER
953 : m_frameToolBar
->m_height
;
955 client_area_y_offset
+= hh
;
958 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
959 m_frameToolBar
->m_widget
,
962 #endif // wxUSE_TOOLBAR
964 int client_x
= client_area_x_offset
+ m_miniEdge
;
965 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
966 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
967 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
968 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
970 client_x
, client_y
, client_w
, client_h
);
974 /* if there is no m_mainWidget between m_widget and m_wxwindow there
975 is no need to set the size or position of m_wxwindow. */
979 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
981 int xx
= 0 + m_miniEdge
;
982 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
983 int ww
= m_width
- 2*m_miniEdge
;
984 int hh
= wxSTATUS_HEIGHT
;
985 m_frameStatusBar
->m_x
= xx
;
986 m_frameStatusBar
->m_y
= yy
;
987 m_frameStatusBar
->m_width
= ww
;
988 m_frameStatusBar
->m_height
= hh
;
989 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
990 m_frameStatusBar
->m_widget
,
992 gtk_widget_draw( m_frameStatusBar
->m_widget
, (GdkRectangle
*) NULL
);
994 #endif // wxUSE_STATUSBAR
998 // send size event to frame
999 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1000 event
.SetEventObject( this );
1001 GetEventHandler()->ProcessEvent( event
);
1004 // send size event to status bar
1005 if (m_frameStatusBar
)
1007 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
1008 event2
.SetEventObject( m_frameStatusBar
);
1009 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
1011 #endif // wxUSE_STATUSBAR
1016 void wxFrameGTK::MakeModal( bool modal
)
1019 gtk_grab_add( m_widget
);
1021 gtk_grab_remove( m_widget
);
1024 void wxFrameGTK::OnInternalIdle()
1026 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1028 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1030 // we'll come back later
1032 wxapp_install_idle_handler();
1037 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
1038 #endif // wxUSE_MENUS
1040 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
1043 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
1046 wxWindow::OnInternalIdle();
1049 // ----------------------------------------------------------------------------
1050 // menu/tool/status bar stuff
1051 // ----------------------------------------------------------------------------
1055 void wxFrameGTK::SetMenuBar( wxMenuBar
*menuBar
)
1057 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1058 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
1060 if (menuBar
== m_frameMenuBar
)
1065 m_frameMenuBar
->UnsetInvokingWindow( this );
1067 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1069 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1070 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1072 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1073 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1076 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
1077 gtk_widget_ref( m_frameMenuBar
->m_widget
);
1078 gtk_widget_unparent( m_frameMenuBar
->m_widget
);
1081 m_frameMenuBar
= menuBar
;
1085 m_frameMenuBar
->SetInvokingWindow( this );
1087 m_frameMenuBar
->SetParent(this);
1088 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
1089 m_frameMenuBar
->m_widget
,
1090 m_frameMenuBar
->m_x
,
1091 m_frameMenuBar
->m_y
,
1092 m_frameMenuBar
->m_width
,
1093 m_frameMenuBar
->m_height
);
1095 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1097 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
1098 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1100 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
1101 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1104 m_frameMenuBar
->Show( TRUE
);
1107 /* resize window in OnInternalIdle */
1111 #endif // wxUSE_MENUS
1115 wxToolBar
* wxFrameGTK::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
1117 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1119 m_insertInClientArea
= FALSE
;
1121 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
1123 m_insertInClientArea
= TRUE
;
1127 return m_frameToolBar
;
1130 void wxFrameGTK::SetToolBar(wxToolBar
*toolbar
)
1132 wxFrameBase::SetToolBar(toolbar
);
1136 /* insert into toolbar area if not already there */
1137 if ((m_frameToolBar
->m_widget
->parent
) &&
1138 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
1140 GetChildren().DeleteObject( m_frameToolBar
);
1142 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
1148 #endif // wxUSE_TOOLBAR
1152 wxStatusBar
* wxFrameGTK::CreateStatusBar(int number
,
1155 const wxString
& name
)
1157 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1159 // because it will change when toolbar is added
1162 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
1165 void wxFrameGTK::PositionStatusBar()
1167 if ( !m_frameStatusBar
)
1172 #endif // wxUSE_STATUSBAR
1174 // ----------------------------------------------------------------------------
1176 // ----------------------------------------------------------------------------
1178 void wxFrameGTK::SetTitle( const wxString
&title
)
1180 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1183 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
1186 void wxFrameGTK::SetIcon( const wxIcon
&icon
)
1188 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1190 wxFrameBase::SetIcon(icon
);
1195 if (!m_widget
->window
)
1198 wxMask
*mask
= icon
.GetMask();
1199 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1200 if (mask
) bm
= mask
->GetBitmap();
1202 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1205 // ----------------------------------------------------------------------------
1206 // frame state: maximized/iconized/normal
1207 // ----------------------------------------------------------------------------
1209 void wxFrameGTK::Maximize(bool WXUNUSED(maximize
))
1211 wxFAIL_MSG( _T("not implemented") );
1214 bool wxFrameGTK::IsMaximized() const
1216 // wxFAIL_MSG( _T("not implemented") );
1218 // This is an approximation
1222 void wxFrameGTK::Restore()
1224 wxFAIL_MSG( _T("not implemented") );
1227 void wxFrameGTK::Iconize( bool iconize
)
1231 GdkWindow
*window
= m_widget
->window
;
1233 // you should do it later, for example from OnCreate() handler
1234 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1236 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1237 GDK_WINDOW_XWINDOW( window
),
1238 DefaultScreen( GDK_DISPLAY() ) );
1242 bool wxFrameGTK::IsIconized() const
1244 return m_isIconized
;
1247 void wxFrameGTK::SetIconizeState(bool iconize
)
1249 if ( iconize
!= m_isIconized
)
1251 m_isIconized
= iconize
;
1252 (void)SendIconizeEvent(iconize
);