]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/toplevel.cpp
patch from Dimitri fixing a few memory leaks and unTABbing the sources
[wxWidgets.git] / src / gtk1 / toplevel.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: toplevel.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 "toplevel.h"
20 #endif
21
22 #ifdef __VMS
23 #define XIconifyWindow XICONIFYWINDOW
24 #endif
25
26 #include "wx/defs.h"
27
28 #include "wx/dialog.h"
29 #include "wx/control.h"
30 #include "wx/app.h"
31 #include "wx/dcclient.h"
32
33 #include <glib.h>
34 #include <gdk/gdk.h>
35 #include <gtk/gtk.h>
36 #include <gdk/gdkkeysyms.h>
37 #include <gdk/gdkx.h>
38
39 #include "wx/gtk/win_gtk.h"
40
41 // ----------------------------------------------------------------------------
42 // idle system
43 // ----------------------------------------------------------------------------
44
45 extern void wxapp_install_idle_handler();
46 extern bool g_isIdle;
47 extern int g_openDialogs;
48
49 // ----------------------------------------------------------------------------
50 // event tables
51 // ----------------------------------------------------------------------------
52
53 // ----------------------------------------------------------------------------
54 // data
55 // ----------------------------------------------------------------------------
56
57 extern wxList wxPendingDelete;
58
59 // ----------------------------------------------------------------------------
60 // debug
61 // ----------------------------------------------------------------------------
62
63 #ifdef __WXDEBUG__
64
65 extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
66
67 #endif
68
69 // ============================================================================
70 // implementation
71 // ============================================================================
72
73 // ----------------------------------------------------------------------------
74 // GTK callbacks
75 // ----------------------------------------------------------------------------
76
77 //-----------------------------------------------------------------------------
78 // "focus" from m_window
79 //-----------------------------------------------------------------------------
80
81 static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
82 {
83 if (g_isIdle)
84 wxapp_install_idle_handler();
85
86 // This disables GTK's tab traversal
87 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
88 return TRUE;
89 }
90
91 //-----------------------------------------------------------------------------
92 // "size_allocate"
93 //-----------------------------------------------------------------------------
94
95 static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxTopLevelWindowGTK *win )
96 {
97 if (g_isIdle)
98 wxapp_install_idle_handler();
99
100 if (!win->m_hasVMT)
101 return;
102
103 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
104 {
105 /*
106 wxPrintf( "OnSize from " );
107 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
108 wxPrintf( win->GetClassInfo()->GetClassName() );
109 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
110 (int)alloc->y,
111 (int)alloc->width,
112 (int)alloc->height );
113 */
114
115 win->m_width = alloc->width;
116 win->m_height = alloc->height;
117 win->m_queuedFullRedraw = TRUE;
118 win->GtkUpdateSize();
119 }
120 }
121
122 //-----------------------------------------------------------------------------
123 // "delete_event"
124 //-----------------------------------------------------------------------------
125
126 static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxTopLevelWindowGTK *win )
127 {
128 if (g_isIdle)
129 wxapp_install_idle_handler();
130
131 if (win->IsEnabled() &&
132 (g_openDialogs == 0 || (win->GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)))
133 win->Close();
134
135 return TRUE;
136 }
137
138
139 //-----------------------------------------------------------------------------
140 // "configure_event"
141 //-----------------------------------------------------------------------------
142
143 static gint
144 gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win )
145 {
146 if (g_isIdle)
147 wxapp_install_idle_handler();
148
149 if (!win->m_hasVMT || !win->IsShown())
150 return FALSE;
151
152 int x = 0;
153 int y = 0;
154 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
155 win->m_x = x;
156 win->m_y = y;
157
158 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
159 mevent.SetEventObject( win );
160 win->GetEventHandler()->ProcessEvent( mevent );
161
162 return FALSE;
163 }
164
165 //-----------------------------------------------------------------------------
166 // "realize" from m_widget
167 //-----------------------------------------------------------------------------
168
169 // we cannot MWM hints and icons before the widget has been realized,
170 // so we do this directly after realization
171
172 static void
173 gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win )
174 {
175 if (g_isIdle)
176 wxapp_install_idle_handler();
177
178 // All this is for Motif Window Manager "hints" and is supposed to be
179 // recognized by other WM as well. Not tested.
180 gdk_window_set_decorations(win->m_widget->window,
181 (GdkWMDecoration)win->m_gdkDecor);
182 gdk_window_set_functions(win->m_widget->window,
183 (GdkWMFunction)win->m_gdkFunc);
184
185 // GTK's shrinking/growing policy
186 if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0)
187 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
188 else
189 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
190
191 // reset the icon
192 wxIcon iconOld = win->GetIcon();
193 if ( iconOld != wxNullIcon )
194 {
195 wxIcon icon( iconOld );
196 win->SetIcon( wxNullIcon );
197 win->SetIcon( icon );
198 }
199
200 // we set the focus to the child that accepts the focus. this
201 // doesn't really have to be done in "realize" but why not?
202 wxWindowList::Node *node = win->GetChildren().GetFirst();
203 while (node)
204 {
205 wxWindow *child = node->GetData();
206 if (child->AcceptsFocus())
207 {
208 child->SetFocus();
209 break;
210 }
211
212 node = node->GetNext();
213 }
214 }
215
216 //-----------------------------------------------------------------------------
217 // "map_event" from m_widget
218 //-----------------------------------------------------------------------------
219
220 static void
221 gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
222 GdkEvent * WXUNUSED(event),
223 wxTopLevelWindow *win )
224 {
225 win->SetIconizeState(FALSE);
226 }
227
228 //-----------------------------------------------------------------------------
229 // "unmap_event" from m_widget
230 //-----------------------------------------------------------------------------
231
232 static void
233 gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
234 GdkEvent * WXUNUSED(event),
235 wxTopLevelWindow *win )
236 {
237 win->SetIconizeState(TRUE);
238 }
239
240 //-----------------------------------------------------------------------------
241 // "expose_event" of m_client
242 //-----------------------------------------------------------------------------
243
244 static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
245 {
246 GtkPizza *pizza = GTK_PIZZA(widget);
247
248 gtk_paint_flat_box (win->m_widget->style,
249 pizza->bin_window, GTK_STATE_NORMAL,
250 GTK_SHADOW_NONE,
251 &gdk_event->area,
252 win->m_widget,
253 (char *)"base",
254 0, 0, -1, -1);
255
256 return TRUE;
257 }
258
259 //-----------------------------------------------------------------------------
260 // "draw" of m_client
261 //-----------------------------------------------------------------------------
262
263
264 static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
265 {
266 GtkPizza *pizza = GTK_PIZZA(widget);
267
268 gtk_paint_flat_box (win->m_widget->style,
269 pizza->bin_window, GTK_STATE_NORMAL,
270 GTK_SHADOW_NONE,
271 rect,
272 win->m_widget,
273 (char *)"base",
274 0, 0, -1, -1);
275 }
276
277 // ----------------------------------------------------------------------------
278 // wxTopLevelWindowGTK itself
279 // ----------------------------------------------------------------------------
280
281 //-----------------------------------------------------------------------------
282 // InsertChild for wxTopLevelWindowGTK
283 //-----------------------------------------------------------------------------
284
285 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
286 * C++ has no virtual methods in a constructor. We have to emulate a
287 * virtual function here as wxWindows requires different ways to insert
288 * a child in container classes. */
289
290 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
291 {
292 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
293
294 if (!parent->m_insertInClientArea)
295 {
296 // these are outside the client area
297 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
298 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
299 GTK_WIDGET(child->m_widget),
300 child->m_x,
301 child->m_y,
302 child->m_width,
303 child->m_height );
304 }
305 else
306 {
307 // these are inside the client area
308 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
309 GTK_WIDGET(child->m_widget),
310 child->m_x,
311 child->m_y,
312 child->m_width,
313 child->m_height );
314 }
315
316 // resize on OnInternalIdle
317 parent->GtkUpdateSize();
318 }
319
320 // ----------------------------------------------------------------------------
321 // wxTopLevelWindowGTK creation
322 // ----------------------------------------------------------------------------
323
324 void wxTopLevelWindowGTK::Init()
325 {
326 m_sizeSet = FALSE;
327 m_miniEdge = 0;
328 m_miniTitle = 0;
329 m_mainWidget = (GtkWidget*) NULL;
330 m_insertInClientArea = TRUE;
331 m_isFrame = TRUE;
332 m_isIconized = FALSE;
333 m_fsIsShowing = FALSE;
334 m_themeEnabled = TRUE;
335 m_gdkDecor = m_gdkFunc = 0;
336 }
337
338 bool wxTopLevelWindowGTK::Create( wxWindow *parent,
339 wxWindowID id,
340 const wxString& title,
341 const wxPoint& pos,
342 const wxSize& sizeOrig,
343 long style,
344 const wxString &name )
345 {
346 // always create a frame of some reasonable, even if arbitrary, size (at
347 // least for MSW compatibility)
348 wxSize size = sizeOrig;
349 if ( size.x == -1 || size.y == -1 )
350 {
351 wxSize sizeDpy = wxGetDisplaySize();
352 if ( size.x == -1 )
353 size.x = sizeDpy.x / 3;
354 if ( size.y == -1 )
355 size.y = sizeDpy.y / 5;
356 }
357
358 wxTopLevelWindows.Append( this );
359
360 m_needParent = FALSE;
361
362 if (!PreCreation( parent, pos, size ) ||
363 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
364 {
365 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
366 return FALSE;
367 }
368
369 m_title = title;
370
371 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
372
373 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
374
375 if (style & wxFRAME_TOOL_WINDOW)
376 win_type = GTK_WINDOW_POPUP;
377
378 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
379 {
380 // there is no more GTK_WINDOW_DIALOG in 2.0
381 #ifdef __WXGTK20__
382 win_type = GTK_WINDOW_TOPLEVEL;
383 #else
384 win_type = GTK_WINDOW_DIALOG;
385 #endif
386 }
387
388 m_widget = gtk_window_new( win_type );
389
390 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)) &&
391 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG))
392 {
393 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
394 }
395
396 if (!name.IsEmpty())
397 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
398
399 #ifdef __WXDEBUG__
400 debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name );
401 #endif
402
403 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
404 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
405
406 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
407 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
408
409 // m_mainWidget holds the toolbar, the menubar and the client area
410 m_mainWidget = gtk_pizza_new();
411 gtk_widget_show( m_mainWidget );
412 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
413 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
414
415 // for m_mainWidget themes
416 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
417 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
418 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
419 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
420
421 #ifdef __WXDEBUG__
422 debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name );
423 #endif
424
425 // m_wxwindow only represents the client area without toolbar and menubar
426 m_wxwindow = gtk_pizza_new();
427 gtk_widget_show( m_wxwindow );
428 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
429
430 #ifdef __WXDEBUG__
431 debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name );
432 #endif
433
434 // we donm't allow the frame to get the focus as otherwise
435 // the frame will grab it at arbitrary focus changes
436 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
437
438 if (m_parent) m_parent->AddChild( this );
439
440 // the user resized the frame by dragging etc.
441 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
442 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
443
444 PostCreation();
445
446 if ((m_x != -1) || (m_y != -1))
447 gtk_widget_set_uposition( m_widget, m_x, m_y );
448
449 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
450
451 // we cannot set MWM hints and icons before the widget has
452 // been realized, so we do this directly after realization
453 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
454 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
455
456 // the only way to get the window size is to connect to this event
457 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
458 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
459
460 // map and unmap for iconized state
461 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
462 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
463 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
464 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
465
466 // the only way to get the window size is to connect to this event
467 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
468 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
469
470 // disable native tab traversal
471 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
472 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
473
474 // decorations
475 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
476 {
477 m_gdkDecor = 0;
478 m_gdkFunc = 0;
479 }
480 else
481 {
482 m_gdkDecor = (long) GDK_DECOR_BORDER;
483 m_gdkFunc = (long) GDK_FUNC_MOVE;
484
485 // All this is for Motif Window Manager "hints" and is supposed to be
486 // recognized by other WMs as well.
487 if ((style & wxCAPTION) != 0)
488 m_gdkDecor |= GDK_DECOR_TITLE;
489 if ((style & wxSYSTEM_MENU) != 0)
490 {
491 m_gdkFunc |= GDK_FUNC_CLOSE;
492 m_gdkDecor |= GDK_DECOR_MENU;
493 }
494 if ((style & wxMINIMIZE_BOX) != 0)
495 {
496 m_gdkFunc |= GDK_FUNC_MINIMIZE;
497 m_gdkDecor |= GDK_DECOR_MINIMIZE;
498 }
499 if ((style & wxMAXIMIZE_BOX) != 0)
500 {
501 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
502 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
503 }
504 if ((style & wxRESIZE_BORDER) != 0)
505 {
506 m_gdkFunc |= GDK_FUNC_RESIZE;
507 m_gdkDecor |= GDK_DECOR_RESIZEH;
508 }
509 }
510
511 return TRUE;
512 }
513
514 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
515 {
516 m_isBeingDeleted = TRUE;
517
518 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
519
520 wxTopLevelWindows.DeleteObject( this );
521
522 if (wxTheApp->GetTopWindow() == this)
523 wxTheApp->SetTopWindow( (wxWindow*) NULL );
524
525 if ((wxTopLevelWindows.Number() == 0) &&
526 (wxTheApp->GetExitOnFrameDelete()))
527 {
528 wxTheApp->ExitMainLoop();
529 }
530 }
531
532 bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
533 {
534 if (show == m_fsIsShowing) return FALSE; // return what?
535
536 m_fsIsShowing = show;
537
538 if (show)
539 {
540 m_fsSaveGdkFunc = m_gdkFunc;
541 m_fsSaveGdkDecor = m_gdkDecor;
542 m_fsSaveFlag = style;
543 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
544 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
545
546 gtk_widget_hide( m_widget );
547 gtk_widget_unrealize( m_widget );
548
549 m_gdkDecor = (long) GDK_DECOR_BORDER;
550 m_gdkFunc = (long) GDK_FUNC_MOVE;
551
552 int x;
553 int y;
554 wxDisplaySize( &x, &y );
555 SetSize( 0, 0, x, y );
556
557 gtk_widget_realize( m_widget );
558 gtk_widget_show( m_widget );
559 }
560 else
561 {
562 gtk_widget_hide( m_widget );
563 gtk_widget_unrealize( m_widget );
564
565 m_gdkFunc = m_fsSaveGdkFunc;
566 m_gdkDecor = m_fsSaveGdkDecor;
567
568 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
569
570 gtk_widget_realize( m_widget );
571 gtk_widget_show( m_widget );
572 }
573
574 return TRUE;
575 }
576
577 // ----------------------------------------------------------------------------
578 // overridden wxWindow methods
579 // ----------------------------------------------------------------------------
580
581 bool wxTopLevelWindowGTK::Show( bool show )
582 {
583 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
584
585 if (show && !m_sizeSet)
586 {
587 /* by calling GtkOnSize here, we don't have to call
588 either after showing the frame, which would entail
589 much ugly flicker or from within the size_allocate
590 handler, because GTK 1.1.X forbids that. */
591
592 GtkOnSize( m_x, m_y, m_width, m_height );
593 }
594
595 return wxWindow::Show( show );
596 }
597
598 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
599 {
600 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
601 }
602
603 void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
604 {
605 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
606
607 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
608 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
609
610 // avoid recursions
611 if (m_resizing)
612 return;
613 m_resizing = TRUE;
614
615 int old_x = m_x;
616 int old_y = m_y;
617
618 int old_width = m_width;
619 int old_height = m_height;
620
621 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
622 {
623 if (x != -1) m_x = x;
624 if (y != -1) m_y = y;
625 if (width != -1) m_width = width;
626 if (height != -1) m_height = height;
627 }
628 else
629 {
630 m_x = x;
631 m_y = y;
632 m_width = width;
633 m_height = height;
634 }
635
636 /*
637 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
638 {
639 if (width == -1) m_width = 80;
640 }
641
642 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
643 {
644 if (height == -1) m_height = 26;
645 }
646 */
647
648 int minWidth = GetMinWidth(),
649 minHeight = GetMinHeight(),
650 maxWidth = GetMaxWidth(),
651 maxHeight = GetMaxHeight();
652
653 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
654 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
655 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
656 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
657
658 if ((m_x != -1) || (m_y != -1))
659 {
660 if ((m_x != old_x) || (m_y != old_y))
661 {
662 gtk_widget_set_uposition( m_widget, m_x, m_y );
663 }
664 }
665
666 if ((m_width != old_width) || (m_height != old_height))
667 {
668 if (m_widget->window)
669 gdk_window_resize( m_widget->window, m_width, m_height );
670 else
671 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
672
673 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
674 done either directly before the frame is shown or in idle time
675 so that different calls to SetSize() don't lead to flicker. */
676 m_sizeSet = FALSE;
677 }
678
679 m_resizing = FALSE;
680 }
681
682 void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
683 {
684 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
685
686 wxWindow::DoGetClientSize( width, height );
687 if (height)
688 {
689 // mini edge
690 *height -= m_miniEdge*2 + m_miniTitle;
691 }
692 if (width)
693 {
694 *width -= m_miniEdge*2;
695 }
696 }
697
698 void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
699 {
700 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
701
702 DoSetSize(-1, -1,
703 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
704 }
705
706 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
707 int width, int height )
708 {
709 // due to a bug in gtk, x,y are always 0
710 // m_x = x;
711 // m_y = y;
712
713 // avoid recursions
714 if (m_resizing) return;
715 m_resizing = TRUE;
716
717 if ( m_wxwindow == NULL ) return;
718
719 m_width = width;
720 m_height = height;
721
722 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
723 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
724 set in wxFrame::Create so it is used to check what kind of frame we
725 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
726 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
727 importantly) m_mainWidget */
728
729 int minWidth = GetMinWidth(),
730 minHeight = GetMinHeight(),
731 maxWidth = GetMaxWidth(),
732 maxHeight = GetMaxHeight();
733
734 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
735 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
736 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
737 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
738
739 if (m_mainWidget)
740 {
741 // set size hints
742 gint flag = 0; // GDK_HINT_POS;
743 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
744 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
745 GdkGeometry geom;
746 geom.min_width = minWidth;
747 geom.min_height = minHeight;
748 geom.max_width = maxWidth;
749 geom.max_height = maxHeight;
750 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
751 (GtkWidget*) NULL,
752 &geom,
753 (GdkWindowHints) flag );
754
755 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
756 * menubar, the toolbar and the client area, which is represented by
757 * m_wxwindow.
758 * this hurts in the eye, but I don't want to call SetSize()
759 * because I don't want to call any non-native functions here. */
760
761 int client_x = m_miniEdge;
762 int client_y = m_miniEdge + m_miniTitle;
763 int client_w = m_width - 2*m_miniEdge;
764 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
765 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
766 m_wxwindow,
767 client_x, client_y, client_w, client_h );
768 }
769 else
770 {
771 // If there is no m_mainWidget between m_widget and m_wxwindow there
772 // is no need to set the size or position of m_wxwindow.
773 }
774
775 m_sizeSet = TRUE;
776
777 // send size event to frame
778 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
779 event.SetEventObject( this );
780 GetEventHandler()->ProcessEvent( event );
781
782 m_resizing = FALSE;
783 }
784
785 void wxTopLevelWindowGTK::OnInternalIdle()
786 {
787 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
788 {
789 GtkOnSize( m_x, m_y, m_width, m_height );
790
791 // we'll come back later
792 if (g_isIdle)
793 wxapp_install_idle_handler();
794 return;
795 }
796
797 wxWindow::OnInternalIdle();
798 }
799
800
801 // ----------------------------------------------------------------------------
802 // frame title/icon
803 // ----------------------------------------------------------------------------
804
805 void wxTopLevelWindowGTK::SetTitle( const wxString &title )
806 {
807 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
808
809 m_title = title;
810 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
811 }
812
813 void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
814 {
815 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
816
817 wxTopLevelWindowBase::SetIcon(icon);
818
819 if ( !m_icon.Ok() )
820 return;
821
822 if (!m_widget->window)
823 return;
824
825 wxMask *mask = icon.GetMask();
826 GdkBitmap *bm = (GdkBitmap *) NULL;
827 if (mask) bm = mask->GetBitmap();
828
829 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
830 }
831
832 // ----------------------------------------------------------------------------
833 // frame state: maximized/iconized/normal
834 // ----------------------------------------------------------------------------
835
836 void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
837 {
838 wxFAIL_MSG( _T("not implemented") );
839 }
840
841 bool wxTopLevelWindowGTK::IsMaximized() const
842 {
843 // wxFAIL_MSG( _T("not implemented") );
844
845 // This is an approximation
846 return FALSE;
847 }
848
849 void wxTopLevelWindowGTK::Restore()
850 {
851 wxFAIL_MSG( _T("not implemented") );
852 }
853
854 void wxTopLevelWindowGTK::Iconize( bool iconize )
855 {
856 if (iconize)
857 {
858 GdkWindow *window = m_widget->window;
859
860 // you should do it later, for example from OnCreate() handler
861 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
862
863 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
864 GDK_WINDOW_XWINDOW( window ),
865 DefaultScreen( GDK_DISPLAY() ) );
866 }
867 }
868
869 bool wxTopLevelWindowGTK::IsIconized() const
870 {
871 return m_isIconized;
872 }
873
874 void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
875 {
876 if ( iconize != m_isIconized )
877 {
878 m_isIconized = iconize;
879 (void)SendIconizeEvent(iconize);
880 }
881 }
882