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 #ifdef __WXUNIVERSAL__
69 IMPLEMENT_DYNAMIC_CLASS(wxFrameGTK
, wxWindow
)
71 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxFrameGTK
)
72 IMPLEMENT_DYNAMIC_CLASS(wxFrameGTK
, wxWindow
)
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
79 extern wxList wxPendingDelete
;
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
87 extern void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
);
91 // ============================================================================
93 // ============================================================================
95 // ----------------------------------------------------------------------------
97 // ----------------------------------------------------------------------------
99 //-----------------------------------------------------------------------------
100 // "focus" from m_window
101 //-----------------------------------------------------------------------------
103 static gint
gtk_frame_focus_callback( GtkWidget
*widget
, GtkDirectionType
WXUNUSED(d
), wxWindow
*WXUNUSED(win
) )
106 wxapp_install_idle_handler();
108 // This disables GTK's tab traversal
109 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus" );
113 //-----------------------------------------------------------------------------
115 //-----------------------------------------------------------------------------
117 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxFrameGTK
*win
)
120 wxapp_install_idle_handler();
125 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
128 wxPrintf( "OnSize from " );
129 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
130 wxPrintf( win->GetClassInfo()->GetClassName() );
131 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
134 (int)alloc->height );
137 win
->m_width
= alloc
->width
;
138 win
->m_height
= alloc
->height
;
139 win
->m_queuedFullRedraw
= TRUE
;
140 win
->GtkUpdateSize();
144 //-----------------------------------------------------------------------------
146 //-----------------------------------------------------------------------------
148 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxFrameGTK
*win
)
151 wxapp_install_idle_handler();
153 if ((g_openDialogs
== 0) && (win
->IsEnabled()))
160 //-----------------------------------------------------------------------------
161 // "child_attached" of menu bar
162 //-----------------------------------------------------------------------------
164 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
166 if (!win
->m_hasVMT
) return;
168 win
->m_menuBarDetached
= FALSE
;
169 win
->GtkUpdateSize();
172 //-----------------------------------------------------------------------------
173 // "child_detached" of menu bar
174 //-----------------------------------------------------------------------------
176 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
178 if (!win
->m_hasVMT
) return;
180 win
->m_menuBarDetached
= TRUE
;
181 win
->GtkUpdateSize();
183 #endif // wxUSE_MENUS
186 //-----------------------------------------------------------------------------
187 // "child_attached" of tool bar
188 //-----------------------------------------------------------------------------
190 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
192 if (!win
->m_hasVMT
) return;
194 win
->m_toolBarDetached
= FALSE
;
196 win
->GtkUpdateSize();
199 //-----------------------------------------------------------------------------
200 // "child_detached" of tool bar
201 //-----------------------------------------------------------------------------
203 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
206 wxapp_install_idle_handler();
208 if (!win
->m_hasVMT
) return;
210 win
->m_toolBarDetached
= TRUE
;
211 win
->GtkUpdateSize();
213 #endif // wxUSE_TOOLBAR
215 //-----------------------------------------------------------------------------
217 //-----------------------------------------------------------------------------
220 #if (GTK_MINOR_VERSION > 0)
221 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxFrameGTK
*win
)
223 gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*event
, wxFrameGTK
*win
)
227 wxapp_install_idle_handler();
232 #if (GTK_MINOR_VERSION > 0)
235 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
243 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
244 mevent
.SetEventObject( win
);
245 win
->GetEventHandler()->ProcessEvent( mevent
);
250 //-----------------------------------------------------------------------------
251 // "realize" from m_widget
252 //-----------------------------------------------------------------------------
254 /* we cannot MWM hints and icons before the widget has been realized,
255 so we do this directly after realization */
258 gtk_frame_realized_callback( GtkWidget
* WXUNUSED(widget
), wxFrameGTK
*win
)
261 wxapp_install_idle_handler();
263 if ((win
->m_miniEdge
> 0) || (win
->HasFlag(wxSIMPLE_BORDER
)) || (win
->HasFlag(wxNO_BORDER
)))
265 /* This is a mini-frame or a borderless frame. */
266 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)0 );
267 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)0 );
271 /* All this is for Motif Window Manager "hints" and is supposed to be
272 recognized by other WM as well. Not tested. */
273 long decor
= (long) GDK_DECOR_BORDER
;
274 long func
= (long) GDK_FUNC_MOVE
;
276 if ((win
->GetWindowStyle() & wxCAPTION
) != 0)
277 decor
|= GDK_DECOR_TITLE
;
278 if ((win
->GetWindowStyle() & wxSYSTEM_MENU
) != 0)
280 decor
|= GDK_DECOR_MENU
;
281 func
|= GDK_FUNC_CLOSE
;
283 if ((win
->GetWindowStyle() & wxMINIMIZE_BOX
) != 0)
285 func
|= GDK_FUNC_MINIMIZE
;
286 decor
|= GDK_DECOR_MINIMIZE
;
288 if ((win
->GetWindowStyle() & wxMAXIMIZE_BOX
) != 0)
290 func
|= GDK_FUNC_MAXIMIZE
;
291 decor
|= GDK_DECOR_MAXIMIZE
;
293 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) != 0)
295 func
|= GDK_FUNC_RESIZE
;
296 decor
|= GDK_DECOR_RESIZEH
;
299 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)decor
);
300 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)func
);
303 /* GTK's shrinking/growing policy */
304 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) == 0)
305 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
307 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
310 wxIcon iconOld
= win
->GetIcon();
311 if ( iconOld
!= wxNullIcon
)
313 wxIcon
icon( iconOld
);
314 win
->SetIcon( wxNullIcon
);
315 win
->SetIcon( icon
);
318 /* we set the focus to the child that accepts the focus. this
319 doesn't really have to be done in "realize" but why not? */
320 wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
323 wxWindow
*child
= node
->GetData();
324 if (child
->AcceptsFocus())
330 node
= node
->GetNext();
334 //-----------------------------------------------------------------------------
335 // "map_event" from m_widget
336 //-----------------------------------------------------------------------------
339 gtk_frame_map_callback( GtkWidget
* WXUNUSED(widget
),
340 GdkEvent
* WXUNUSED(event
),
343 win
->SetIconizeState(FALSE
);
346 //-----------------------------------------------------------------------------
347 // "unmap_event" from m_widget
348 //-----------------------------------------------------------------------------
351 gtk_frame_unmap_callback( GtkWidget
* WXUNUSED(widget
),
352 GdkEvent
* WXUNUSED(event
),
355 win
->SetIconizeState(TRUE
);
358 //-----------------------------------------------------------------------------
359 // "expose_event" of m_client
360 //-----------------------------------------------------------------------------
362 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
364 GtkPizza
*pizza
= GTK_PIZZA(widget
);
366 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
367 GTK_SHADOW_NONE
, &gdk_event
->area
, win
->m_widget
, "base", 0, 0, -1, -1);
372 //-----------------------------------------------------------------------------
373 // "draw" of m_client
374 //-----------------------------------------------------------------------------
377 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
379 GtkPizza
*pizza
= GTK_PIZZA(widget
);
381 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
382 GTK_SHADOW_NONE
, rect
, win
->m_widget
, "base", 0, 0, -1, -1);
385 // ----------------------------------------------------------------------------
387 // ----------------------------------------------------------------------------
389 //-----------------------------------------------------------------------------
390 // InsertChild for wxFrameGTK
391 //-----------------------------------------------------------------------------
393 /* Callback for wxFrameGTK. This very strange beast has to be used because
394 * C++ has no virtual methods in a constructor. We have to emulate a
395 * virtual function here as wxWindows requires different ways to insert
396 * a child in container classes. */
398 static void wxInsertChildInFrame( wxFrameGTK
* parent
, wxWindow
* child
)
400 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
402 if (!parent
->m_insertInClientArea
)
404 /* these are outside the client area */
405 wxFrameGTK
* frame
= (wxFrameGTK
*) parent
;
406 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
407 GTK_WIDGET(child
->m_widget
),
413 #if wxUSE_TOOLBAR_NATIVE
414 /* we connect to these events for recalculating the client area
415 space when the toolbar is floating */
416 if (wxIS_KIND_OF(child
,wxToolBar
))
418 wxToolBar
*toolBar
= (wxToolBar
*) child
;
419 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
421 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
422 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
424 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
425 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
428 #endif // wxUSE_TOOLBAR
432 /* these are inside the client area */
433 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
434 GTK_WIDGET(child
->m_widget
),
441 /* resize on OnInternalIdle */
442 parent
->GtkUpdateSize();
445 // ----------------------------------------------------------------------------
446 // wxFrameGTK creation
447 // ----------------------------------------------------------------------------
449 void wxFrameGTK::Init()
454 m_mainWidget
= (GtkWidget
*) NULL
;
455 m_menuBarDetached
= FALSE
;
456 m_toolBarDetached
= FALSE
;
457 m_insertInClientArea
= TRUE
;
459 m_isIconized
= FALSE
;
460 m_fsIsShowing
= FALSE
;
461 m_themeEnabled
= TRUE
;
464 bool wxFrameGTK::Create( wxWindow
*parent
,
466 const wxString
& title
,
468 const wxSize
& sizeOrig
,
470 const wxString
&name
)
472 // always create a frame of some reasonable, even if arbitrary, size (at
473 // least for MSW compatibility)
474 wxSize size
= sizeOrig
;
475 if ( size
.x
== -1 || size
.y
== -1 )
477 wxSize sizeDpy
= wxGetDisplaySize();
479 size
.x
= sizeDpy
.x
/ 3;
481 size
.y
= sizeDpy
.y
/ 5;
484 wxTopLevelWindows
.Append( this );
486 m_needParent
= FALSE
;
488 if (!PreCreation( parent
, pos
, size
) ||
489 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
491 wxFAIL_MSG( wxT("wxFrameGTK creation failed") );
497 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
499 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
501 if (style
& wxFRAME_TOOL_WINDOW
)
502 win_type
= GTK_WINDOW_POPUP
;
504 m_widget
= gtk_window_new( win_type
);
506 if ((m_parent
) && (HasFlag(wxFRAME_FLOAT_ON_PARENT
)) && (GTK_IS_WINDOW(m_parent
->m_widget
)))
507 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
510 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), name
.mb_str(), name
.mb_str() );
513 debug_focus_in( m_widget
, wxT("wxFrameGTK::m_widget"), name
);
516 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
517 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
519 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
520 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
522 /* m_mainWidget holds the toolbar, the menubar and the client area */
523 m_mainWidget
= gtk_pizza_new();
524 gtk_widget_show( m_mainWidget
);
525 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
526 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
528 /* for m_mainWidget themes */
529 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "expose_event",
530 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
531 gtk_signal_connect( GTK_OBJECT(m_mainWidget
), "draw",
532 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
535 debug_focus_in( m_mainWidget
, wxT("wxFrameGTK::m_mainWidget"), name
);
538 /* m_wxwindow only represents the client area without toolbar and menubar */
539 m_wxwindow
= gtk_pizza_new();
540 gtk_widget_show( m_wxwindow
);
541 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
544 debug_focus_in( m_wxwindow
, wxT("wxFrameGTK::m_wxwindow"), name
);
547 /* we donm't allow the frame to get the focus as otherwise
548 the frame will grab it at arbitrary focus changes. */
549 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
551 if (m_parent
) m_parent
->AddChild( this );
553 /* the user resized the frame by dragging etc. */
554 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
555 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
559 if ((m_x
!= -1) || (m_y
!= -1))
560 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
561 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
563 /* we cannot set MWM hints and icons before the widget has
564 been realized, so we do this directly after realization */
565 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
566 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
568 /* the only way to get the window size is to connect to this event */
569 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
570 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
572 /* map and unmap for iconized state */
573 gtk_signal_connect( GTK_OBJECT(m_widget
), "map_event",
574 GTK_SIGNAL_FUNC(gtk_frame_map_callback
), (gpointer
)this );
575 gtk_signal_connect( GTK_OBJECT(m_widget
), "unmap_event",
576 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback
), (gpointer
)this );
578 /* the only way to get the window size is to connect to this event */
579 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
580 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
582 /* disable native tab traversal */
583 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus",
584 GTK_SIGNAL_FUNC(gtk_frame_focus_callback
), (gpointer
)this );
589 wxFrameGTK::~wxFrameGTK()
591 m_isBeingDeleted
= TRUE
;
595 wxTopLevelWindows
.DeleteObject( this );
597 if (wxTheApp
->GetTopWindow() == this)
598 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
600 if ((wxTopLevelWindows
.Number() == 0) &&
601 (wxTheApp
->GetExitOnFrameDelete()))
603 wxTheApp
->ExitMainLoop();
607 bool wxFrameGTK::ShowFullScreen(bool show
, long style
)
609 if (show
== m_fsIsShowing
) return FALSE
; // return what?
611 m_fsIsShowing
= show
;
615 m_fsSaveStyle
= m_windowStyle
;
616 m_fsSaveFlag
= style
;
617 GetPosition( &m_fsSaveFrame
.x
, &m_fsSaveFrame
.y
);
618 GetSize( &m_fsSaveFrame
.width
, &m_fsSaveFrame
.height
);
620 gtk_widget_hide( m_widget
);
621 gtk_widget_unrealize( m_widget
);
623 m_windowStyle
= wxSIMPLE_BORDER
;
627 wxDisplaySize( &x
, &y
);
628 SetSize( 0, 0, x
, y
);
630 gtk_widget_realize( m_widget
);
631 gtk_widget_show( m_widget
);
635 gtk_widget_hide( m_widget
);
636 gtk_widget_unrealize( m_widget
);
638 m_windowStyle
= m_fsSaveStyle
;
640 SetSize( m_fsSaveFrame
.x
, m_fsSaveFrame
.y
, m_fsSaveFrame
.width
, m_fsSaveFrame
.height
);
642 gtk_widget_realize( m_widget
);
643 gtk_widget_show( m_widget
);
649 // ----------------------------------------------------------------------------
650 // overridden wxWindow methods
651 // ----------------------------------------------------------------------------
653 bool wxFrameGTK::Show( bool show
)
655 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
657 if (show
&& !m_sizeSet
)
659 /* by calling GtkOnSize here, we don't have to call
660 either after showing the frame, which would entail
661 much ugly flicker or from within the size_allocate
662 handler, because GTK 1.1.X forbids that. */
664 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
667 return wxWindow::Show( show
);
670 void wxFrameGTK::DoMoveWindow(int WXUNUSED(x
), int WXUNUSED(y
), int WXUNUSED(width
), int WXUNUSED(height
) )
672 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrameGTK") );
675 void wxFrameGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
677 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
679 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
680 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
682 /* avoid recursions */
690 int old_width
= m_width
;
691 int old_height
= m_height
;
693 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
695 if (x
!= -1) m_x
= x
;
696 if (y
!= -1) m_y
= y
;
697 if (width
!= -1) m_width
= width
;
698 if (height
!= -1) m_height
= height
;
709 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
711 if (width == -1) m_width = 80;
714 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
716 if (height == -1) m_height = 26;
720 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
721 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
722 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
723 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
725 if ((m_x
!= -1) || (m_y
!= -1))
727 if ((m_x
!= old_x
) || (m_y
!= old_y
))
729 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
733 if ((m_width
!= old_width
) || (m_height
!= old_height
))
735 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
737 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
738 done either directly before the frame is shown or in idle time
739 so that different calls to SetSize() don't lead to flicker. */
746 void wxFrameGTK::DoGetClientSize( int *width
, int *height
) const
748 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
750 wxWindow::DoGetClientSize( width
, height
);
757 if (!m_menuBarDetached
)
758 (*height
) -= wxMENU_HEIGHT
;
760 (*height
) -= wxPLACE_HOLDER
;
762 #endif // wxUSE_MENUS
766 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) (*height
) -= wxSTATUS_HEIGHT
;
767 #endif // wxUSE_STATUSBAR
771 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
773 if (m_toolBarDetached
)
775 *height
-= wxPLACE_HOLDER
;
780 m_frameToolBar
->GetSize( &x
, &y
);
781 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
791 #endif // wxUSE_TOOLBAR
794 *height
-= m_miniEdge
*2 + m_miniTitle
;
798 *width
-= m_miniEdge
*2;
802 void wxFrameGTK::DoSetClientSize( int width
, int height
)
804 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
810 if (!m_menuBarDetached
)
811 height
+= wxMENU_HEIGHT
;
813 height
+= wxPLACE_HOLDER
;
815 #endif // wxUSE_MENUS
819 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
824 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
826 if (m_toolBarDetached
)
828 height
+= wxPLACE_HOLDER
;
833 m_frameToolBar
->GetSize( &x
, &y
);
834 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
846 DoSetSize( -1, -1, width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
, 0 );
849 void wxFrameGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
850 int width
, int height
)
852 // due to a bug in gtk, x,y are always 0
856 /* avoid recursions */
857 if (m_resizing
) return;
860 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
861 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
866 /* space occupied by m_frameToolBar and m_frameMenuBar */
867 int client_area_x_offset
= 0,
868 client_area_y_offset
= 0;
870 /* wxMDIChildFrame derives from wxFrameGTK but it _is_ a wxWindow as it uses
871 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
872 set in wxFrameGTK::Create so it is used to check what kind of frame we
873 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
874 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
875 importantly) m_mainWidget */
877 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
878 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
879 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
880 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
885 gint flag
= 0; // GDK_HINT_POS;
886 if ((m_minWidth
!= -1) || (m_minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
887 if ((m_maxWidth
!= -1) || (m_maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
889 geom
.min_width
= m_minWidth
;
890 geom
.min_height
= m_minHeight
;
891 geom
.max_width
= m_maxWidth
;
892 geom
.max_height
= m_maxHeight
;
893 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
896 (GdkWindowHints
) flag
);
898 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
899 * menubar, the toolbar and the client area, which is represented by
901 * this hurts in the eye, but I don't want to call SetSize()
902 * because I don't want to call any non-native functions here. */
908 int yy
= m_miniEdge
+ m_miniTitle
;
909 int ww
= m_width
- 2*m_miniEdge
;
910 int hh
= wxMENU_HEIGHT
;
911 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
912 m_frameMenuBar
->m_x
= xx
;
913 m_frameMenuBar
->m_y
= yy
;
914 m_frameMenuBar
->m_width
= ww
;
915 m_frameMenuBar
->m_height
= hh
;
916 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
917 m_frameMenuBar
->m_widget
,
919 client_area_y_offset
+= hh
;
921 #endif // wxUSE_MENUS
924 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
925 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
928 int yy
= m_miniEdge
+ m_miniTitle
;
932 if (!m_menuBarDetached
)
935 yy
+= wxPLACE_HOLDER
;
937 #endif // wxUSE_MENUS
939 m_frameToolBar
->m_x
= xx
;
940 m_frameToolBar
->m_y
= yy
;
942 /* don't change the toolbar's reported height/width */
944 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
946 ww
= m_toolBarDetached
? wxPLACE_HOLDER
947 : m_frameToolBar
->m_width
;
948 hh
= m_height
- 2*m_miniEdge
;
950 client_area_x_offset
+= ww
;
954 ww
= m_width
- 2*m_miniEdge
;
955 hh
= m_toolBarDetached
? wxPLACE_HOLDER
956 : m_frameToolBar
->m_height
;
958 client_area_y_offset
+= hh
;
961 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
962 m_frameToolBar
->m_widget
,
965 #endif // wxUSE_TOOLBAR
967 int client_x
= client_area_x_offset
+ m_miniEdge
;
968 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
969 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
970 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
971 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
973 client_x
, client_y
, client_w
, client_h
);
977 /* if there is no m_mainWidget between m_widget and m_wxwindow there
978 is no need to set the size or position of m_wxwindow. */
982 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
984 int xx
= 0 + m_miniEdge
;
985 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
986 int ww
= m_width
- 2*m_miniEdge
;
987 int hh
= wxSTATUS_HEIGHT
;
988 m_frameStatusBar
->m_x
= xx
;
989 m_frameStatusBar
->m_y
= yy
;
990 m_frameStatusBar
->m_width
= ww
;
991 m_frameStatusBar
->m_height
= hh
;
992 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
993 m_frameStatusBar
->m_widget
,
995 gtk_widget_draw( m_frameStatusBar
->m_widget
, (GdkRectangle
*) NULL
);
997 #endif // wxUSE_STATUSBAR
1001 // send size event to frame
1002 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1003 event
.SetEventObject( this );
1004 GetEventHandler()->ProcessEvent( event
);
1007 // send size event to status bar
1008 if (m_frameStatusBar
)
1010 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
1011 event2
.SetEventObject( m_frameStatusBar
);
1012 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
1014 #endif // wxUSE_STATUSBAR
1019 void wxFrameGTK::MakeModal( bool modal
)
1022 gtk_grab_add( m_widget
);
1024 gtk_grab_remove( m_widget
);
1027 void wxFrameGTK::OnInternalIdle()
1029 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
1031 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
1033 // we'll come back later
1035 wxapp_install_idle_handler();
1040 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
1041 #endif // wxUSE_MENUS
1043 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
1046 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
1049 wxWindow::OnInternalIdle();
1052 // ----------------------------------------------------------------------------
1053 // menu/tool/status bar stuff
1054 // ----------------------------------------------------------------------------
1058 void wxFrameGTK::SetMenuBar( wxMenuBar
*menuBar
)
1060 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1061 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
1063 if (menuBar
== m_frameMenuBar
)
1068 m_frameMenuBar
->UnsetInvokingWindow( this );
1070 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1072 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1073 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1075 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
1076 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1079 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
1080 gtk_widget_ref( m_frameMenuBar
->m_widget
);
1081 gtk_widget_unparent( m_frameMenuBar
->m_widget
);
1084 m_frameMenuBar
= menuBar
;
1088 m_frameMenuBar
->SetInvokingWindow( this );
1090 m_frameMenuBar
->SetParent(this);
1091 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
1092 m_frameMenuBar
->m_widget
,
1093 m_frameMenuBar
->m_x
,
1094 m_frameMenuBar
->m_y
,
1095 m_frameMenuBar
->m_width
,
1096 m_frameMenuBar
->m_height
);
1098 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
1100 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
1101 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
1103 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
1104 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
1107 m_frameMenuBar
->Show( TRUE
);
1110 /* resize window in OnInternalIdle */
1114 #endif // wxUSE_MENUS
1118 wxToolBar
* wxFrameGTK::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
1120 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1122 m_insertInClientArea
= FALSE
;
1124 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
1126 m_insertInClientArea
= TRUE
;
1130 return m_frameToolBar
;
1133 void wxFrameGTK::SetToolBar(wxToolBar
*toolbar
)
1135 wxFrameBase::SetToolBar(toolbar
);
1139 /* insert into toolbar area if not already there */
1140 if ((m_frameToolBar
->m_widget
->parent
) &&
1141 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
1143 GetChildren().DeleteObject( m_frameToolBar
);
1145 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
1151 #endif // wxUSE_TOOLBAR
1155 wxStatusBar
* wxFrameGTK::CreateStatusBar(int number
,
1158 const wxString
& name
)
1160 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1162 // because it will change when toolbar is added
1165 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
1168 void wxFrameGTK::PositionStatusBar()
1170 if ( !m_frameStatusBar
)
1175 #endif // wxUSE_STATUSBAR
1177 // ----------------------------------------------------------------------------
1179 // ----------------------------------------------------------------------------
1181 void wxFrameGTK::SetTitle( const wxString
&title
)
1183 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1186 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
1189 void wxFrameGTK::SetIcon( const wxIcon
&icon
)
1191 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
1193 wxFrameBase::SetIcon(icon
);
1198 if (!m_widget
->window
)
1201 wxMask
*mask
= icon
.GetMask();
1202 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1203 if (mask
) bm
= mask
->GetBitmap();
1205 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);
1208 // ----------------------------------------------------------------------------
1209 // frame state: maximized/iconized/normal
1210 // ----------------------------------------------------------------------------
1212 void wxFrameGTK::Maximize(bool WXUNUSED(maximize
))
1214 wxFAIL_MSG( _T("not implemented") );
1217 bool wxFrameGTK::IsMaximized() const
1219 // wxFAIL_MSG( _T("not implemented") );
1221 // This is an approximation
1225 void wxFrameGTK::Restore()
1227 wxFAIL_MSG( _T("not implemented") );
1230 void wxFrameGTK::Iconize( bool iconize
)
1234 GdkWindow
*window
= m_widget
->window
;
1236 // you should do it later, for example from OnCreate() handler
1237 wxCHECK_RET( window
, _T("frame not created yet - can't iconize") );
1239 XIconifyWindow( GDK_WINDOW_XDISPLAY( window
),
1240 GDK_WINDOW_XWINDOW( window
),
1241 DefaultScreen( GDK_DISPLAY() ) );
1245 bool wxFrameGTK::IsIconized() const
1247 return m_isIconized
;
1250 void wxFrameGTK::SetIconizeState(bool iconize
)
1252 if ( iconize
!= m_isIconized
)
1254 m_isIconized
= iconize
;
1255 (void)SendIconizeEvent(iconize
);