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