Fixed missing paint events when overriding DoMoveWindow()
[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 /* I haven't been able to set the position of
252 the dialog before it is shown, so I set the
253 position in "realize" */
254 gtk_widget_set_uposition( widget, win->m_x, win->m_y );
255
256 /* all this is for Motif Window Manager "hints" and is supposed to be
257 recognized by other WM as well. not tested. */
258 long decor = (long) GDK_DECOR_BORDER;
259 long func = (long) GDK_FUNC_MOVE;
260
261 if ((win->GetWindowStyle() & wxCAPTION) != 0)
262 decor |= GDK_DECOR_TITLE;
263 if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
264 {
265 decor |= GDK_DECOR_MENU;
266 func |= GDK_FUNC_CLOSE;
267 }
268 if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
269 {
270 func |= GDK_FUNC_MINIMIZE;
271 decor |= GDK_DECOR_MINIMIZE;
272 }
273 if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
274 {
275 func |= GDK_FUNC_MAXIMIZE;
276 decor |= GDK_DECOR_MAXIMIZE;
277 }
278 if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
279 {
280 func |= GDK_FUNC_RESIZE;
281 decor |= GDK_DECOR_RESIZEH;
282 }
283
284 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
285 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
286
287 /* GTK's shrinking/growing policy */
288 if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
289 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
290 else
291 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
292
293 /* set size hints */
294 gint flag = 0; // GDK_HINT_POS;
295 if ((win->GetMinWidth() != -1) || (win->GetMinHeight() != -1)) flag |= GDK_HINT_MIN_SIZE;
296 if ((win->GetMaxWidth() != -1) || (win->GetMaxHeight() != -1)) flag |= GDK_HINT_MAX_SIZE;
297 if (flag)
298 {
299 gdk_window_set_hints( win->m_widget->window,
300 win->m_x, win->m_y,
301 win->GetMinWidth(), win->GetMinHeight(),
302 win->GetMaxWidth(), win->GetMaxHeight(),
303 flag );
304 }
305
306 /* reset the icon */
307 wxIcon iconOld = win->GetIcon();
308 if ( iconOld != wxNullIcon )
309 {
310 wxIcon icon( iconOld );
311 win->SetIcon( wxNullIcon );
312 win->SetIcon( icon );
313 }
314
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();
318 while (node)
319 {
320 wxWindow *child = node->GetData();
321 if (child->AcceptsFocus())
322 {
323 child->SetFocus();
324 break;
325 }
326
327 node = node->GetNext();
328 }
329
330 return FALSE;
331 }
332
333 // ----------------------------------------------------------------------------
334 // wxFrame itself
335 // ----------------------------------------------------------------------------
336
337 //-----------------------------------------------------------------------------
338 // InsertChild for wxFrame
339 //-----------------------------------------------------------------------------
340
341 /* Callback for wxFrame. This very strange beast has to be used because
342 * C++ has no virtual methods in a constructor. We have to emulate a
343 * virtual function here as wxWindows requires different ways to insert
344 * a child in container classes. */
345
346 static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
347 {
348 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
349
350 if (!parent->m_insertInClientArea)
351 {
352 /* these are outside the client area */
353 wxFrame* frame = (wxFrame*) parent;
354 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
355 GTK_WIDGET(child->m_widget),
356 child->m_x,
357 child->m_y,
358 child->m_width,
359 child->m_height );
360
361 #if wxUSE_TOOLBAR_NATIVE
362 /* we connect to these events for recalculating the client area
363 space when the toolbar is floating */
364 if (wxIS_KIND_OF(child,wxToolBar))
365 {
366 wxToolBar *toolBar = (wxToolBar*) child;
367 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
368 {
369 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
370 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
371
372 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
373 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
374 }
375 }
376 #endif // wxUSE_TOOLBAR
377 }
378 else
379 {
380 /* these are inside the client area */
381 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
382 GTK_WIDGET(child->m_widget),
383 child->m_x,
384 child->m_y,
385 child->m_width,
386 child->m_height );
387 }
388
389 /* resize on OnInternalIdle */
390 parent->GtkUpdateSize();
391 }
392
393 // ----------------------------------------------------------------------------
394 // wxFrame creation
395 // ----------------------------------------------------------------------------
396
397 void wxFrame::Init()
398 {
399 m_sizeSet = FALSE;
400 m_miniEdge = 0;
401 m_miniTitle = 0;
402 m_mainWidget = (GtkWidget*) NULL;
403 m_menuBarDetached = FALSE;
404 m_toolBarDetached = FALSE;
405 m_insertInClientArea = TRUE;
406 m_isFrame = FALSE;
407 }
408
409 bool wxFrame::Create( wxWindow *parent,
410 wxWindowID id,
411 const wxString &title,
412 const wxPoint &pos,
413 const wxSize &size,
414 long style,
415 const wxString &name )
416 {
417 wxTopLevelWindows.Append( this );
418
419 m_needParent = FALSE;
420 m_isFrame = TRUE;
421
422 if (!PreCreation( parent, pos, size ) ||
423 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
424 {
425 wxFAIL_MSG( wxT("wxFrame creation failed") );
426 return FALSE;
427 }
428
429 m_title = title;
430
431 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
432
433 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
434 if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP;
435
436 m_widget = gtk_window_new( win_type );
437
438 if (!name.IsEmpty())
439 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
440
441 #ifdef __WXDEBUG__
442 debug_focus_in( m_widget, wxT("wxFrame::m_widget"), name );
443 #endif
444
445 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
446 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
447
448 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
449 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
450
451 /* m_mainWidget holds the toolbar, the menubar and the client area */
452 m_mainWidget = gtk_pizza_new();
453 gtk_widget_show( m_mainWidget );
454 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
455 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
456
457 #ifdef __WXDEBUG__
458 debug_focus_in( m_mainWidget, wxT("wxFrame::m_mainWidget"), name );
459 #endif
460
461 /* m_wxwindow only represents the client area without toolbar and menubar */
462 m_wxwindow = gtk_pizza_new();
463 gtk_widget_show( m_wxwindow );
464 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
465
466 #ifdef __WXDEBUG__
467 debug_focus_in( m_wxwindow, wxT("wxFrame::m_wxwindow"), name );
468 #endif
469
470 /* we donm't allow the frame to get the focus as otherwise
471 the frame will grabit at arbitrary fcous changes. */
472 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
473
474 if (m_parent) m_parent->AddChild( this );
475
476 /* the user resized the frame by dragging etc. */
477 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
478 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
479
480 PostCreation();
481
482 /* we cannot set MWM hints and icons before the widget has
483 been realized, so we do this directly after realization */
484 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
485 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
486
487 /* the only way to get the window size is to connect to this event */
488 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
489 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
490
491 /* disable native tab traversal */
492 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
493 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
494
495 return TRUE;
496 }
497
498 wxFrame::~wxFrame()
499 {
500 m_isBeingDeleted = TRUE;
501
502 DeleteAllBars();
503
504 wxTopLevelWindows.DeleteObject( this );
505
506 if (wxTheApp->GetTopWindow() == this)
507 wxTheApp->SetTopWindow( (wxWindow*) NULL );
508
509 if ((wxTopLevelWindows.Number() == 0) &&
510 (wxTheApp->GetExitOnFrameDelete()))
511 {
512 wxTheApp->ExitMainLoop();
513 }
514 }
515
516 // ----------------------------------------------------------------------------
517 // overridden wxWindow methods
518 // ----------------------------------------------------------------------------
519
520 bool wxFrame::Show( bool show )
521 {
522 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
523
524 if (show && !m_sizeSet)
525 {
526 /* by calling GtkOnSize here, we don't have to call
527 either after showing the frame, which would entail
528 much ugly flicker or from within the size_allocate
529 handler, because GTK 1.1.X forbids that. */
530
531 GtkOnSize( m_x, m_y, m_width, m_height );
532 }
533
534 return wxWindow::Show( show );
535 }
536
537 void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
538 {
539 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
540 }
541
542 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
543 {
544 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
545
546 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
547 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
548
549 /* avoid recursions */
550 if (m_resizing)
551 return;
552 m_resizing = TRUE;
553
554 int old_x = m_x;
555 int old_y = m_y;
556
557 int old_width = m_width;
558 int old_height = m_height;
559
560 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
561 {
562 if (x != -1) m_x = x;
563 if (y != -1) m_y = y;
564 if (width != -1) m_width = width;
565 if (height != -1) m_height = height;
566 }
567 else
568 {
569 m_x = x;
570 m_y = y;
571 m_width = width;
572 m_height = height;
573 }
574
575 /*
576 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
577 {
578 if (width == -1) m_width = 80;
579 }
580
581 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
582 {
583 if (height == -1) m_height = 26;
584 }
585 */
586
587 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
588 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
589 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
590 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
591
592 if ((m_x != -1) || (m_y != -1))
593 {
594 if ((m_x != old_x) || (m_y != old_y))
595 {
596 gtk_widget_set_uposition( m_widget, m_x, m_y );
597 }
598 }
599
600 if ((m_width != old_width) || (m_height != old_height))
601 {
602 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
603 done either directly before the frame is shown or in idle time
604 so that different calls to SetSize() don't lead to flicker. */
605 m_sizeSet = FALSE;
606 }
607
608 m_resizing = FALSE;
609 }
610
611 void wxFrame::DoGetClientSize( int *width, int *height ) const
612 {
613 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
614
615 wxWindow::DoGetClientSize( width, height );
616 if (height)
617 {
618 /* menu bar */
619 if (m_frameMenuBar)
620 {
621 if (!m_menuBarDetached)
622 (*height) -= wxMENU_HEIGHT;
623 else
624 (*height) -= wxPLACE_HOLDER;
625 }
626
627 #if wxUSE_STATUSBAR
628 /* status bar */
629 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
630 #endif // wxUSE_STATUSBAR
631
632 #if wxUSE_TOOLBAR
633 /* tool bar */
634 if (m_frameToolBar)
635 {
636 if (m_toolBarDetached)
637 {
638 *height -= wxPLACE_HOLDER;
639 }
640 else
641 {
642 int x, y;
643 m_frameToolBar->GetSize( &x, &y );
644 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
645 {
646 *width -= x;
647 }
648 else
649 {
650 *height -= y;
651 }
652 }
653 }
654 #endif // wxUSE_TOOLBAR
655
656 /* mini edge */
657 *height -= m_miniEdge*2 + m_miniTitle;
658 }
659 if (width)
660 {
661 *width -= m_miniEdge*2;
662 }
663 }
664
665 void wxFrame::DoSetClientSize( int width, int height )
666 {
667 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
668
669 /* menu bar */
670 if (m_frameMenuBar)
671 {
672 if (!m_menuBarDetached)
673 height += wxMENU_HEIGHT;
674 else
675 height += wxPLACE_HOLDER;
676 }
677
678 #if wxUSE_STATUSBAR
679 /* status bar */
680 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
681 #endif
682
683 #if wxUSE_TOOLBAR
684 /* tool bar */
685 if (m_frameToolBar)
686 {
687 if (m_toolBarDetached)
688 {
689 height += wxPLACE_HOLDER;
690 }
691 else
692 {
693 int x, y;
694 m_frameToolBar->GetSize( &x, &y );
695 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
696 {
697 width += x;
698 }
699 else
700 {
701 height += y;
702 }
703 }
704 }
705 #endif
706
707 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
708 }
709
710 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
711 int width, int height )
712 {
713 // due to a bug in gtk, x,y are always 0
714 // m_x = x;
715 // m_y = y;
716
717 /* avoid recursions */
718 if (m_resizing) return;
719 m_resizing = TRUE;
720
721 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
722 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
723
724 m_width = width;
725 m_height = height;
726
727 /* space occupied by m_frameToolBar and m_frameMenuBar */
728 int client_area_x_offset = 0,
729 client_area_y_offset = 0;
730
731 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
732 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
733 set in wxFrame::Create so it is used to check what kind of frame we
734 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
735 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
736 importantly) m_mainWidget */
737
738 if (m_mainWidget)
739 {
740 /* check if size is in legal range */
741 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
742 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
743 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
744 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
745
746 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
747 * menubar, the toolbar and the client area, which is represented by
748 * m_wxwindow.
749 * this hurts in the eye, but I don't want to call SetSize()
750 * because I don't want to call any non-native functions here. */
751
752 if (m_frameMenuBar)
753 {
754 int xx = m_miniEdge;
755 int yy = m_miniEdge + m_miniTitle;
756 int ww = m_width - 2*m_miniEdge;
757 int hh = wxMENU_HEIGHT;
758 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
759 m_frameMenuBar->m_x = xx;
760 m_frameMenuBar->m_y = yy;
761 m_frameMenuBar->m_width = ww;
762 m_frameMenuBar->m_height = hh;
763 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
764 m_frameMenuBar->m_widget,
765 xx, yy, ww, hh );
766 client_area_y_offset += hh;
767 }
768
769 #if wxUSE_TOOLBAR
770 if ((m_frameToolBar) &&
771 (m_frameToolBar->m_widget->parent == m_mainWidget))
772 {
773 int xx = m_miniEdge;
774 int yy = m_miniEdge + m_miniTitle;
775 if (m_frameMenuBar)
776 {
777 if (!m_menuBarDetached)
778 yy += wxMENU_HEIGHT;
779 else
780 yy += wxPLACE_HOLDER;
781 }
782
783 m_frameToolBar->m_x = xx;
784 m_frameToolBar->m_y = yy;
785
786 /* don't change the toolbar's reported height/width */
787 int ww, hh;
788 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
789 {
790 ww = m_toolBarDetached ? wxPLACE_HOLDER
791 : m_frameToolBar->m_width;
792 hh = m_height - 2*m_miniEdge;
793
794 client_area_x_offset += ww;
795 }
796 else
797 {
798 ww = m_width - 2*m_miniEdge;
799 hh = m_toolBarDetached ? wxPLACE_HOLDER
800 : m_frameToolBar->m_height;
801
802 client_area_y_offset += hh;
803 }
804
805 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
806 m_frameToolBar->m_widget,
807 xx, yy, ww, hh );
808 }
809 #endif // wxUSE_TOOLBAR
810
811 int client_x = client_area_x_offset + m_miniEdge;
812 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
813 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
814 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
815 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
816 m_wxwindow,
817 client_x, client_y, client_w, client_h );
818 }
819 else
820 {
821 /* if there is no m_mainWidget between m_widget and m_wxwindow there
822 is no need to set the size or position of m_wxwindow. */
823 }
824
825 #if wxUSE_STATUSBAR
826 if (m_frameStatusBar)
827 {
828 int xx = 0 + m_miniEdge;
829 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
830 int ww = m_width - 2*m_miniEdge;
831 int hh = wxSTATUS_HEIGHT;
832 m_frameStatusBar->m_x = xx;
833 m_frameStatusBar->m_y = yy;
834 m_frameStatusBar->m_width = ww;
835 m_frameStatusBar->m_height = hh;
836 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
837 m_frameStatusBar->m_widget,
838 xx, yy, ww, hh );
839 gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
840 }
841 #endif
842
843 /* we actually set the size of a frame here and no-where else */
844 gtk_widget_set_usize( m_widget, m_width, m_height );
845
846 m_sizeSet = TRUE;
847
848 // send size event to frame
849 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
850 event.SetEventObject( this );
851 GetEventHandler()->ProcessEvent( event );
852
853 // send size event to status bar
854 if (m_frameStatusBar)
855 {
856 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
857 event2.SetEventObject( m_frameStatusBar );
858 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
859 }
860
861 m_resizing = FALSE;
862 }
863
864 void wxFrame::MakeModal( bool modal )
865 {
866 if (modal)
867 gtk_grab_add( m_widget );
868 else
869 gtk_grab_remove( m_widget );
870 }
871
872 void wxFrame::OnInternalIdle()
873 {
874 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
875 {
876 GtkOnSize( m_x, m_y, m_width, m_height );
877
878 // we'll come back later
879 if (g_isIdle)
880 wxapp_install_idle_handler();
881 return;
882 }
883
884 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
885 #if wxUSE_TOOLBAR
886 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
887 #endif
888 #if wxUSE_STATUSBAR
889 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
890 #endif
891
892 wxWindow::OnInternalIdle();
893 }
894
895 // ----------------------------------------------------------------------------
896 // menu/tool/status bar stuff
897 // ----------------------------------------------------------------------------
898
899 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
900 {
901 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
902 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
903
904 if (menuBar == m_frameMenuBar)
905 return;
906
907 if (m_frameMenuBar)
908 {
909 m_frameMenuBar->UnsetInvokingWindow( this );
910
911 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
912 {
913 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
914 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
915
916 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
917 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
918 }
919
920 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
921 gtk_widget_ref( m_frameMenuBar->m_widget );
922 gtk_widget_unparent( m_frameMenuBar->m_widget );
923 }
924
925 m_frameMenuBar = menuBar;
926
927 if (m_frameMenuBar)
928 {
929 m_frameMenuBar->SetInvokingWindow( this );
930
931 m_frameMenuBar->SetParent(this);
932 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
933 m_frameMenuBar->m_widget,
934 m_frameMenuBar->m_x,
935 m_frameMenuBar->m_y,
936 m_frameMenuBar->m_width,
937 m_frameMenuBar->m_height );
938
939 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
940 {
941 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
942 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
943
944 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
945 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
946 }
947
948 m_frameMenuBar->Show( TRUE );
949 }
950
951 /* resize window in OnInternalIdle */
952 m_sizeSet = FALSE;
953 }
954
955 #if wxUSE_TOOLBAR
956 wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
957 {
958 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
959
960 m_insertInClientArea = FALSE;
961
962 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
963
964 if (m_frameToolBar)
965 GetChildren().DeleteObject( m_frameToolBar );
966
967 m_insertInClientArea = TRUE;
968
969 m_sizeSet = FALSE;
970
971 return m_frameToolBar;
972 }
973
974 void wxFrame::SetToolBar(wxToolBar *toolbar)
975 {
976 wxFrameBase::SetToolBar(toolbar);
977
978 if (m_frameToolBar)
979 {
980 /* insert into toolbar area if not already there */
981 if ((m_frameToolBar->m_widget->parent) &&
982 (m_frameToolBar->m_widget->parent != m_mainWidget))
983 {
984 GetChildren().DeleteObject( m_frameToolBar );
985
986 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
987 GtkUpdateSize();
988 }
989 }
990 }
991
992 #endif // wxUSE_TOOLBAR
993
994 #if wxUSE_STATUSBAR
995
996 wxStatusBar* wxFrame::CreateStatusBar(int number,
997 long style,
998 wxWindowID id,
999 const wxString& name)
1000 {
1001 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1002
1003 // because it will change when toolbar is added
1004 m_sizeSet = FALSE;
1005
1006 return wxFrameBase::CreateStatusBar( number, style, id, name );
1007 }
1008
1009 void wxFrame::PositionStatusBar()
1010 {
1011 if ( !m_frameStatusBar )
1012 return;
1013
1014 m_sizeSet = FALSE;
1015 }
1016 #endif // wxUSE_STATUSBAR
1017
1018 // ----------------------------------------------------------------------------
1019 // frame title/icon
1020 // ----------------------------------------------------------------------------
1021
1022 void wxFrame::SetTitle( const wxString &title )
1023 {
1024 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1025
1026 m_title = title;
1027 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
1028 }
1029
1030 void wxFrame::SetIcon( const wxIcon &icon )
1031 {
1032 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1033
1034 wxFrameBase::SetIcon(icon);
1035
1036 if ( !m_icon.Ok() )
1037 return;
1038
1039 if (!m_widget->window)
1040 return;
1041
1042 wxMask *mask = icon.GetMask();
1043 GdkBitmap *bm = (GdkBitmap *) NULL;
1044 if (mask) bm = mask->GetBitmap();
1045
1046 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
1047 }
1048
1049 // ----------------------------------------------------------------------------
1050 // frame state: maximized/iconized/normal (TODO)
1051 // ----------------------------------------------------------------------------
1052
1053 void wxFrame::Maximize(bool WXUNUSED(maximize))
1054 {
1055 }
1056
1057 bool wxFrame::IsMaximized() const
1058 {
1059 return FALSE;
1060 }
1061
1062 void wxFrame::Restore()
1063 {
1064 }
1065
1066 void wxFrame::Iconize( bool iconize )
1067 {
1068 if (iconize)
1069 {
1070 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
1071 GDK_WINDOW_XWINDOW( m_widget->window ),
1072 DefaultScreen( GDK_DISPLAY() ) );
1073 }
1074 }
1075
1076 bool wxFrame::IsIconized() const
1077 {
1078 return FALSE;
1079 }