The Return of WM Size Hints Part IV.
[wxWidgets.git] / src / gtk1 / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 #ifdef __GNUG__
19 #pragma implementation "frame.h"
20 #endif
21
22 #include "wx/frame.h"
23 #include "wx/dialog.h"
24 #include "wx/control.h"
25 #include "wx/app.h"
26 #include "wx/menu.h"
27 #if wxUSE_TOOLBAR
28 #include "wx/toolbar.h"
29 #endif
30 #if wxUSE_STATUSBAR
31 #include "wx/statusbr.h"
32 #endif
33 #include "wx/dcclient.h"
34
35 #include <glib.h>
36 #include <gdk/gdk.h>
37 #include <gtk/gtk.h>
38 #include <gdk/gdkkeysyms.h>
39 #include <gdk/gdkx.h>
40
41 #include "wx/gtk/win_gtk.h"
42
43 // ----------------------------------------------------------------------------
44 // constants
45 // ----------------------------------------------------------------------------
46
47 const int wxMENU_HEIGHT = 27;
48 const int wxSTATUS_HEIGHT = 25;
49 const int wxPLACE_HOLDER = 0;
50
51 // ----------------------------------------------------------------------------
52 // idle system
53 // ----------------------------------------------------------------------------
54
55 extern void wxapp_install_idle_handler();
56 extern bool g_isIdle;
57 extern int g_openDialogs;
58
59 // ----------------------------------------------------------------------------
60 // event tables
61 // ----------------------------------------------------------------------------
62
63 IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
64
65 // ----------------------------------------------------------------------------
66 // data
67 // ----------------------------------------------------------------------------
68
69 extern wxList wxPendingDelete;
70
71 // ----------------------------------------------------------------------------
72 // debug
73 // ----------------------------------------------------------------------------
74
75 #ifdef __WXDEBUG__
76
77 extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
78
79 #endif
80
81 // ============================================================================
82 // implementation
83 // ============================================================================
84
85 // ----------------------------------------------------------------------------
86 // GTK callbacks
87 // ----------------------------------------------------------------------------
88
89 //-----------------------------------------------------------------------------
90 // "focus" from m_window
91 //-----------------------------------------------------------------------------
92
93 static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
94 {
95 if (g_isIdle)
96 wxapp_install_idle_handler();
97
98 // This disables GTK's tab traversal
99 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
100 return TRUE;
101 }
102
103 //-----------------------------------------------------------------------------
104 // "size_allocate"
105 //-----------------------------------------------------------------------------
106
107 static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
108 {
109 if (g_isIdle)
110 wxapp_install_idle_handler();
111
112 if (!win->m_hasVMT)
113 return;
114
115 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
116 {
117 /*
118 wxPrintf( "OnSize from " );
119 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
120 wxPrintf( win->GetClassInfo()->GetClassName() );
121 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
122 (int)alloc->y,
123 (int)alloc->width,
124 (int)alloc->height );
125 */
126
127 win->m_width = alloc->width;
128 win->m_height = alloc->height;
129 win->m_queuedFullRedraw = TRUE;
130 win->GtkUpdateSize();
131 }
132 }
133
134 //-----------------------------------------------------------------------------
135 // "delete_event"
136 //-----------------------------------------------------------------------------
137
138 static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
139 {
140 if (g_isIdle)
141 wxapp_install_idle_handler();
142
143 if ((g_openDialogs == 0) && (win->IsEnabled()))
144 win->Close();
145
146 return TRUE;
147 }
148
149 //-----------------------------------------------------------------------------
150 // "child_attached" of menu bar
151 //-----------------------------------------------------------------------------
152
153 static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
154 {
155 if (!win->m_hasVMT) return;
156
157 win->m_menuBarDetached = FALSE;
158 win->GtkUpdateSize();
159 }
160
161 //-----------------------------------------------------------------------------
162 // "child_detached" of menu bar
163 //-----------------------------------------------------------------------------
164
165 static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
166 {
167 if (!win->m_hasVMT) return;
168
169 win->m_menuBarDetached = TRUE;
170 win->GtkUpdateSize();
171 }
172
173 #if wxUSE_TOOLBAR
174 //-----------------------------------------------------------------------------
175 // "child_attached" of tool bar
176 //-----------------------------------------------------------------------------
177
178 static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
179 {
180 if (!win->m_hasVMT) return;
181
182 win->m_toolBarDetached = FALSE;
183
184 win->GtkUpdateSize();
185 }
186
187 //-----------------------------------------------------------------------------
188 // "child_detached" of tool bar
189 //-----------------------------------------------------------------------------
190
191 static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
192 {
193 if (g_isIdle)
194 wxapp_install_idle_handler();
195
196 if (!win->m_hasVMT) return;
197
198 win->m_toolBarDetached = TRUE;
199 win->GtkUpdateSize();
200 }
201 #endif // wxUSE_TOOLBAR
202
203 //-----------------------------------------------------------------------------
204 // "configure_event"
205 //-----------------------------------------------------------------------------
206
207 static gint
208 #if (GTK_MINOR_VERSION > 0)
209 gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxFrame *win )
210 #else
211 gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxFrame *win )
212 #endif
213 {
214 if (g_isIdle)
215 wxapp_install_idle_handler();
216
217 if (!win->m_hasVMT)
218 return FALSE;
219
220 #if (GTK_MINOR_VERSION > 0)
221 int x = 0;
222 int y = 0;
223 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
224 win->m_x = x;
225 win->m_y = y;
226 #else
227 win->m_x = event->x;
228 win->m_y = event->y;
229 #endif
230
231 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
232 mevent.SetEventObject( win );
233 win->GetEventHandler()->ProcessEvent( mevent );
234
235 return FALSE;
236 }
237
238 //-----------------------------------------------------------------------------
239 // "realize" from m_widget
240 //-----------------------------------------------------------------------------
241
242 /* we cannot MWM hints and icons before the widget has been realized,
243 so we do this directly after realization */
244
245 static gint
246 gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
247 {
248 if (g_isIdle)
249 wxapp_install_idle_handler();
250
251 if ((win->m_miniEdge > 0) || (win->HasFlag(wxSIMPLE_BORDER)))
252 {
253 /* This is a mini-frame or a borderless frame. */
254 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)0 );
255 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)0 );
256 }
257 else
258 {
259 /* All this is for Motif Window Manager "hints" and is supposed to be
260 recognized by other WM as well. Not tested. */
261 long decor = (long) GDK_DECOR_BORDER;
262 long func = (long) GDK_FUNC_MOVE;
263
264 if ((win->GetWindowStyle() & wxCAPTION) != 0)
265 decor |= GDK_DECOR_TITLE;
266 if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
267 {
268 decor |= GDK_DECOR_MENU;
269 func |= GDK_FUNC_CLOSE;
270 }
271 if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
272 {
273 func |= GDK_FUNC_MINIMIZE;
274 decor |= GDK_DECOR_MINIMIZE;
275 }
276 if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
277 {
278 func |= GDK_FUNC_MAXIMIZE;
279 decor |= GDK_DECOR_MAXIMIZE;
280 }
281 if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
282 {
283 func |= GDK_FUNC_RESIZE;
284 decor |= GDK_DECOR_RESIZEH;
285 }
286
287 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
288 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
289 }
290
291 /* GTK's shrinking/growing policy */
292 if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
293 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
294 else
295 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
296
297 /* reset the icon */
298 wxIcon iconOld = win->GetIcon();
299 if ( iconOld != wxNullIcon )
300 {
301 wxIcon icon( iconOld );
302 win->SetIcon( wxNullIcon );
303 win->SetIcon( icon );
304 }
305
306 /* we set the focus to the child that accepts the focus. this
307 doesn't really have to be done in "realize" but why not? */
308 wxWindowList::Node *node = win->GetChildren().GetFirst();
309 while (node)
310 {
311 wxWindow *child = node->GetData();
312 if (child->AcceptsFocus())
313 {
314 child->SetFocus();
315 break;
316 }
317
318 node = node->GetNext();
319 }
320
321 return FALSE;
322 }
323
324 // ----------------------------------------------------------------------------
325 // wxFrame itself
326 // ----------------------------------------------------------------------------
327
328 //-----------------------------------------------------------------------------
329 // InsertChild for wxFrame
330 //-----------------------------------------------------------------------------
331
332 /* Callback for wxFrame. This very strange beast has to be used because
333 * C++ has no virtual methods in a constructor. We have to emulate a
334 * virtual function here as wxWindows requires different ways to insert
335 * a child in container classes. */
336
337 static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
338 {
339 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
340
341 if (!parent->m_insertInClientArea)
342 {
343 /* these are outside the client area */
344 wxFrame* frame = (wxFrame*) parent;
345 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
346 GTK_WIDGET(child->m_widget),
347 child->m_x,
348 child->m_y,
349 child->m_width,
350 child->m_height );
351
352 #if wxUSE_TOOLBAR_NATIVE
353 /* we connect to these events for recalculating the client area
354 space when the toolbar is floating */
355 if (wxIS_KIND_OF(child,wxToolBar))
356 {
357 wxToolBar *toolBar = (wxToolBar*) child;
358 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
359 {
360 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
361 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
362
363 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
364 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
365 }
366 }
367 #endif // wxUSE_TOOLBAR
368 }
369 else
370 {
371 /* these are inside the client area */
372 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
373 GTK_WIDGET(child->m_widget),
374 child->m_x,
375 child->m_y,
376 child->m_width,
377 child->m_height );
378 }
379
380 /* resize on OnInternalIdle */
381 parent->GtkUpdateSize();
382 }
383
384 // ----------------------------------------------------------------------------
385 // wxFrame creation
386 // ----------------------------------------------------------------------------
387
388 void wxFrame::Init()
389 {
390 m_sizeSet = FALSE;
391 m_miniEdge = 0;
392 m_miniTitle = 0;
393 m_mainWidget = (GtkWidget*) NULL;
394 m_menuBarDetached = FALSE;
395 m_toolBarDetached = FALSE;
396 m_insertInClientArea = TRUE;
397 m_isFrame = FALSE;
398 }
399
400 bool wxFrame::Create( wxWindow *parent,
401 wxWindowID id,
402 const wxString &title,
403 const wxPoint &pos,
404 const wxSize &size,
405 long style,
406 const wxString &name )
407 {
408 wxTopLevelWindows.Append( this );
409
410 m_needParent = FALSE;
411 m_isFrame = TRUE;
412
413 if (!PreCreation( parent, pos, size ) ||
414 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
415 {
416 wxFAIL_MSG( wxT("wxFrame creation failed") );
417 return FALSE;
418 }
419
420 m_title = title;
421
422 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
423
424 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
425
426 m_widget = gtk_window_new( win_type );
427
428 if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget)))
429 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
430
431 if (!name.IsEmpty())
432 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
433
434 #ifdef __WXDEBUG__
435 debug_focus_in( m_widget, wxT("wxFrame::m_widget"), name );
436 #endif
437
438 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
439 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
440
441 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
442 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
443
444 /* m_mainWidget holds the toolbar, the menubar and the client area */
445 m_mainWidget = gtk_pizza_new();
446 gtk_widget_show( m_mainWidget );
447 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
448 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
449
450 #ifdef __WXDEBUG__
451 debug_focus_in( m_mainWidget, wxT("wxFrame::m_mainWidget"), name );
452 #endif
453
454 /* m_wxwindow only represents the client area without toolbar and menubar */
455 m_wxwindow = gtk_pizza_new();
456 gtk_widget_show( m_wxwindow );
457 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
458
459 #ifdef __WXDEBUG__
460 debug_focus_in( m_wxwindow, wxT("wxFrame::m_wxwindow"), name );
461 #endif
462
463 /* we donm't allow the frame to get the focus as otherwise
464 the frame will grabit at arbitrary fcous changes. */
465 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
466
467 if (m_parent) m_parent->AddChild( this );
468
469 /* the user resized the frame by dragging etc. */
470 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
471 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
472
473 PostCreation();
474
475 if ((m_x != -1) || (m_y != -1))
476 gtk_widget_set_uposition( m_widget, m_x, m_y );
477 gtk_widget_set_usize( m_widget, m_width, m_height );
478
479 /* we cannot set MWM hints and icons before the widget has
480 been realized, so we do this directly after realization */
481 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
482 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
483
484 /* the only way to get the window size is to connect to this event */
485 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
486 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
487
488 /* disable native tab traversal */
489 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
490 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
491
492 return TRUE;
493 }
494
495 wxFrame::~wxFrame()
496 {
497 m_isBeingDeleted = TRUE;
498
499 DeleteAllBars();
500
501 wxTopLevelWindows.DeleteObject( this );
502
503 if (wxTheApp->GetTopWindow() == this)
504 wxTheApp->SetTopWindow( (wxWindow*) NULL );
505
506 if ((wxTopLevelWindows.Number() == 0) &&
507 (wxTheApp->GetExitOnFrameDelete()))
508 {
509 wxTheApp->ExitMainLoop();
510 }
511 }
512
513 // ----------------------------------------------------------------------------
514 // overridden wxWindow methods
515 // ----------------------------------------------------------------------------
516
517 bool wxFrame::Show( bool show )
518 {
519 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
520
521 if (show && !m_sizeSet)
522 {
523 /* by calling GtkOnSize here, we don't have to call
524 either after showing the frame, which would entail
525 much ugly flicker or from within the size_allocate
526 handler, because GTK 1.1.X forbids that. */
527
528 GtkOnSize( m_x, m_y, m_width, m_height );
529 }
530
531 return wxWindow::Show( show );
532 }
533
534 void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
535 {
536 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
537 }
538
539 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
540 {
541 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
542
543 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
544 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
545
546 /* avoid recursions */
547 if (m_resizing)
548 return;
549 m_resizing = TRUE;
550
551 int old_x = m_x;
552 int old_y = m_y;
553
554 int old_width = m_width;
555 int old_height = m_height;
556
557 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
558 {
559 if (x != -1) m_x = x;
560 if (y != -1) m_y = y;
561 if (width != -1) m_width = width;
562 if (height != -1) m_height = height;
563 }
564 else
565 {
566 m_x = x;
567 m_y = y;
568 m_width = width;
569 m_height = height;
570 }
571
572 /*
573 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
574 {
575 if (width == -1) m_width = 80;
576 }
577
578 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
579 {
580 if (height == -1) m_height = 26;
581 }
582 */
583
584 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
585 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
586 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
587 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
588
589 if ((m_x != -1) || (m_y != -1))
590 {
591 if ((m_x != old_x) || (m_y != old_y))
592 {
593 gtk_widget_set_uposition( m_widget, m_x, m_y );
594 }
595 }
596
597 if ((m_width != old_width) || (m_height != old_height))
598 {
599 gtk_widget_set_usize( m_widget, m_width, m_height );
600
601 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
602 done either directly before the frame is shown or in idle time
603 so that different calls to SetSize() don't lead to flicker. */
604 m_sizeSet = FALSE;
605 }
606
607 m_resizing = FALSE;
608 }
609
610 void wxFrame::DoGetClientSize( int *width, int *height ) const
611 {
612 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
613
614 wxWindow::DoGetClientSize( width, height );
615 if (height)
616 {
617 /* menu bar */
618 if (m_frameMenuBar)
619 {
620 if (!m_menuBarDetached)
621 (*height) -= wxMENU_HEIGHT;
622 else
623 (*height) -= wxPLACE_HOLDER;
624 }
625
626 #if wxUSE_STATUSBAR
627 /* status bar */
628 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
629 #endif // wxUSE_STATUSBAR
630
631 #if wxUSE_TOOLBAR
632 /* tool bar */
633 if (m_frameToolBar)
634 {
635 if (m_toolBarDetached)
636 {
637 *height -= wxPLACE_HOLDER;
638 }
639 else
640 {
641 int x, y;
642 m_frameToolBar->GetSize( &x, &y );
643 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
644 {
645 *width -= x;
646 }
647 else
648 {
649 *height -= y;
650 }
651 }
652 }
653 #endif // wxUSE_TOOLBAR
654
655 /* mini edge */
656 *height -= m_miniEdge*2 + m_miniTitle;
657 }
658 if (width)
659 {
660 *width -= m_miniEdge*2;
661 }
662 }
663
664 void wxFrame::DoSetClientSize( int width, int height )
665 {
666 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
667
668 /* menu bar */
669 if (m_frameMenuBar)
670 {
671 if (!m_menuBarDetached)
672 height += wxMENU_HEIGHT;
673 else
674 height += wxPLACE_HOLDER;
675 }
676
677 #if wxUSE_STATUSBAR
678 /* status bar */
679 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
680 #endif
681
682 #if wxUSE_TOOLBAR
683 /* tool bar */
684 if (m_frameToolBar)
685 {
686 if (m_toolBarDetached)
687 {
688 height += wxPLACE_HOLDER;
689 }
690 else
691 {
692 int x, y;
693 m_frameToolBar->GetSize( &x, &y );
694 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
695 {
696 width += x;
697 }
698 else
699 {
700 height += y;
701 }
702 }
703 }
704 #endif
705
706 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
707 }
708
709 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
710 int width, int height )
711 {
712 // due to a bug in gtk, x,y are always 0
713 // m_x = x;
714 // m_y = y;
715
716 /* avoid recursions */
717 if (m_resizing) return;
718 m_resizing = TRUE;
719
720 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
721 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
722
723 m_width = width;
724 m_height = height;
725
726 /* space occupied by m_frameToolBar and m_frameMenuBar */
727 int client_area_x_offset = 0,
728 client_area_y_offset = 0;
729
730 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
731 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
732 set in wxFrame::Create so it is used to check what kind of frame we
733 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
734 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
735 importantly) m_mainWidget */
736
737 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
738 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
739 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
740 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
741
742 /* set size hints */
743 gint flag = 0; // GDK_HINT_POS;
744 if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
745 if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
746 GdkGeometry geom;
747 geom.min_width = m_minWidth;
748 geom.min_height = m_minHeight;
749 geom.max_width = m_maxWidth;
750 geom.max_height = m_maxHeight;
751 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
752 (GtkWidget*) NULL,
753 &geom,
754 (GdkWindowHints) flag );
755
756 if (m_mainWidget)
757 {
758
759 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
760 * menubar, the toolbar and the client area, which is represented by
761 * m_wxwindow.
762 * this hurts in the eye, but I don't want to call SetSize()
763 * because I don't want to call any non-native functions here. */
764
765 if (m_frameMenuBar)
766 {
767 int xx = m_miniEdge;
768 int yy = m_miniEdge + m_miniTitle;
769 int ww = m_width - 2*m_miniEdge;
770 int hh = wxMENU_HEIGHT;
771 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
772 m_frameMenuBar->m_x = xx;
773 m_frameMenuBar->m_y = yy;
774 m_frameMenuBar->m_width = ww;
775 m_frameMenuBar->m_height = hh;
776 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
777 m_frameMenuBar->m_widget,
778 xx, yy, ww, hh );
779 client_area_y_offset += hh;
780 }
781
782 #if wxUSE_TOOLBAR
783 if ((m_frameToolBar) &&
784 (m_frameToolBar->m_widget->parent == m_mainWidget))
785 {
786 int xx = m_miniEdge;
787 int yy = m_miniEdge + m_miniTitle;
788 if (m_frameMenuBar)
789 {
790 if (!m_menuBarDetached)
791 yy += wxMENU_HEIGHT;
792 else
793 yy += wxPLACE_HOLDER;
794 }
795
796 m_frameToolBar->m_x = xx;
797 m_frameToolBar->m_y = yy;
798
799 /* don't change the toolbar's reported height/width */
800 int ww, hh;
801 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
802 {
803 ww = m_toolBarDetached ? wxPLACE_HOLDER
804 : m_frameToolBar->m_width;
805 hh = m_height - 2*m_miniEdge;
806
807 client_area_x_offset += ww;
808 }
809 else
810 {
811 ww = m_width - 2*m_miniEdge;
812 hh = m_toolBarDetached ? wxPLACE_HOLDER
813 : m_frameToolBar->m_height;
814
815 client_area_y_offset += hh;
816 }
817
818 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
819 m_frameToolBar->m_widget,
820 xx, yy, ww, hh );
821 }
822 #endif // wxUSE_TOOLBAR
823
824 int client_x = client_area_x_offset + m_miniEdge;
825 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
826 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
827 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
828 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
829 m_wxwindow,
830 client_x, client_y, client_w, client_h );
831 }
832 else
833 {
834 /* if there is no m_mainWidget between m_widget and m_wxwindow there
835 is no need to set the size or position of m_wxwindow. */
836 }
837
838 #if wxUSE_STATUSBAR
839 if (m_frameStatusBar)
840 {
841 int xx = 0 + m_miniEdge;
842 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
843 int ww = m_width - 2*m_miniEdge;
844 int hh = wxSTATUS_HEIGHT;
845 m_frameStatusBar->m_x = xx;
846 m_frameStatusBar->m_y = yy;
847 m_frameStatusBar->m_width = ww;
848 m_frameStatusBar->m_height = hh;
849 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
850 m_frameStatusBar->m_widget,
851 xx, yy, ww, hh );
852 gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
853 }
854 #endif
855
856 m_sizeSet = TRUE;
857
858 // send size event to frame
859 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
860 event.SetEventObject( this );
861 GetEventHandler()->ProcessEvent( event );
862
863 // send size event to status bar
864 if (m_frameStatusBar)
865 {
866 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
867 event2.SetEventObject( m_frameStatusBar );
868 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
869 }
870
871 m_resizing = FALSE;
872 }
873
874 void wxFrame::MakeModal( bool modal )
875 {
876 if (modal)
877 gtk_grab_add( m_widget );
878 else
879 gtk_grab_remove( m_widget );
880 }
881
882 void wxFrame::OnInternalIdle()
883 {
884 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
885 {
886 GtkOnSize( m_x, m_y, m_width, m_height );
887
888 // we'll come back later
889 if (g_isIdle)
890 wxapp_install_idle_handler();
891 return;
892 }
893
894 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
895 #if wxUSE_TOOLBAR
896 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
897 #endif
898 #if wxUSE_STATUSBAR
899 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
900 #endif
901
902 wxWindow::OnInternalIdle();
903 }
904
905 // ----------------------------------------------------------------------------
906 // menu/tool/status bar stuff
907 // ----------------------------------------------------------------------------
908
909 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
910 {
911 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
912 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
913
914 if (menuBar == m_frameMenuBar)
915 return;
916
917 if (m_frameMenuBar)
918 {
919 m_frameMenuBar->UnsetInvokingWindow( this );
920
921 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
922 {
923 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
924 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
925
926 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
927 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
928 }
929
930 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
931 gtk_widget_ref( m_frameMenuBar->m_widget );
932 gtk_widget_unparent( m_frameMenuBar->m_widget );
933 }
934
935 m_frameMenuBar = menuBar;
936
937 if (m_frameMenuBar)
938 {
939 m_frameMenuBar->SetInvokingWindow( this );
940
941 m_frameMenuBar->SetParent(this);
942 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
943 m_frameMenuBar->m_widget,
944 m_frameMenuBar->m_x,
945 m_frameMenuBar->m_y,
946 m_frameMenuBar->m_width,
947 m_frameMenuBar->m_height );
948
949 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
950 {
951 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
952 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
953
954 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
955 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
956 }
957
958 m_frameMenuBar->Show( TRUE );
959 }
960
961 /* resize window in OnInternalIdle */
962 m_sizeSet = FALSE;
963 }
964
965 #if wxUSE_TOOLBAR
966 wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
967 {
968 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
969
970 m_insertInClientArea = FALSE;
971
972 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
973
974 if (m_frameToolBar)
975 GetChildren().DeleteObject( m_frameToolBar );
976
977 m_insertInClientArea = TRUE;
978
979 m_sizeSet = FALSE;
980
981 return m_frameToolBar;
982 }
983
984 void wxFrame::SetToolBar(wxToolBar *toolbar)
985 {
986 wxFrameBase::SetToolBar(toolbar);
987
988 if (m_frameToolBar)
989 {
990 /* insert into toolbar area if not already there */
991 if ((m_frameToolBar->m_widget->parent) &&
992 (m_frameToolBar->m_widget->parent != m_mainWidget))
993 {
994 GetChildren().DeleteObject( m_frameToolBar );
995
996 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
997 GtkUpdateSize();
998 }
999 }
1000 }
1001
1002 #endif // wxUSE_TOOLBAR
1003
1004 #if wxUSE_STATUSBAR
1005
1006 wxStatusBar* wxFrame::CreateStatusBar(int number,
1007 long style,
1008 wxWindowID id,
1009 const wxString& name)
1010 {
1011 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1012
1013 // because it will change when toolbar is added
1014 m_sizeSet = FALSE;
1015
1016 return wxFrameBase::CreateStatusBar( number, style, id, name );
1017 }
1018
1019 void wxFrame::PositionStatusBar()
1020 {
1021 if ( !m_frameStatusBar )
1022 return;
1023
1024 m_sizeSet = FALSE;
1025 }
1026 #endif // wxUSE_STATUSBAR
1027
1028 // ----------------------------------------------------------------------------
1029 // frame title/icon
1030 // ----------------------------------------------------------------------------
1031
1032 void wxFrame::SetTitle( const wxString &title )
1033 {
1034 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1035
1036 m_title = title;
1037 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
1038 }
1039
1040 void wxFrame::SetIcon( const wxIcon &icon )
1041 {
1042 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1043
1044 wxFrameBase::SetIcon(icon);
1045
1046 if ( !m_icon.Ok() )
1047 return;
1048
1049 if (!m_widget->window)
1050 return;
1051
1052 wxMask *mask = icon.GetMask();
1053 GdkBitmap *bm = (GdkBitmap *) NULL;
1054 if (mask) bm = mask->GetBitmap();
1055
1056 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
1057 }
1058
1059 // ----------------------------------------------------------------------------
1060 // frame state: maximized/iconized/normal (TODO)
1061 // ----------------------------------------------------------------------------
1062
1063 void wxFrame::Maximize(bool WXUNUSED(maximize))
1064 {
1065 }
1066
1067 bool wxFrame::IsMaximized() const
1068 {
1069 return FALSE;
1070 }
1071
1072 void wxFrame::Restore()
1073 {
1074 }
1075
1076 void wxFrame::Iconize( bool iconize )
1077 {
1078 if (iconize)
1079 {
1080 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
1081 GDK_WINDOW_XWINDOW( m_widget->window ),
1082 DefaultScreen( GDK_DISPLAY() ) );
1083 }
1084 }
1085
1086 bool wxFrame::IsIconized() const
1087 {
1088 return FALSE;
1089 }