]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/toplevel.cpp
use WS_EX_CONTROLPARENT to ensure correct Alt-mnemonic handling with nested panels
[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_isIconized = FALSE;
302 m_fsIsShowing = FALSE;
303 m_themeEnabled = TRUE;
304 m_gdkDecor = m_gdkFunc = 0;
305 }
306
307 bool wxTopLevelWindowGTK::Create( wxWindow *parent,
308 wxWindowID id,
309 const wxString& title,
310 const wxPoint& pos,
311 const wxSize& sizeOrig,
312 long style,
313 const wxString &name )
314 {
315 // always create a frame of some reasonable, even if arbitrary, size (at
316 // least for MSW compatibility)
317 wxSize size = sizeOrig;
318 if ( size.x == -1 || size.y == -1 )
319 {
320 wxSize sizeDpy = wxGetDisplaySize();
321 if ( size.x == -1 )
322 size.x = sizeDpy.x / 3;
323 if ( size.y == -1 )
324 size.y = sizeDpy.y / 5;
325 }
326
327 wxTopLevelWindows.Append( this );
328
329 m_needParent = FALSE;
330
331 if (!PreCreation( parent, pos, size ) ||
332 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
333 {
334 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
335 return FALSE;
336 }
337
338 m_title = title;
339
340 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
341
342 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
343
344 if (style & wxFRAME_TOOL_WINDOW)
345 win_type = GTK_WINDOW_POPUP;
346
347 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
348 {
349 // there is no more GTK_WINDOW_DIALOG in 2.0
350 #ifdef __WXGTK20__
351 win_type = GTK_WINDOW_TOPLEVEL;
352 #else
353 win_type = GTK_WINDOW_DIALOG;
354 #endif
355 }
356
357 m_widget = gtk_window_new( win_type );
358
359 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)) &&
360 (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG))
361 {
362 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
363 }
364
365 if (!name.IsEmpty())
366 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
367
368 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
369 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
370
371 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
372 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
373
374 // m_mainWidget holds the toolbar, the menubar and the client area
375 m_mainWidget = gtk_pizza_new();
376 gtk_widget_show( m_mainWidget );
377 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
378 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
379
380 // for m_mainWidget themes
381 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
382 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
383 #ifndef __WXGTK20__
384 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
385 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
386 #endif
387
388 // m_wxwindow only represents the client area without toolbar and menubar
389 m_wxwindow = gtk_pizza_new();
390 gtk_widget_show( m_wxwindow );
391 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
392
393 // we donm't allow the frame to get the focus as otherwise
394 // the frame will grab it at arbitrary focus changes
395 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
396
397 if (m_parent) m_parent->AddChild( this );
398
399 // the user resized the frame by dragging etc.
400 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
401 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
402
403 PostCreation();
404
405 if ((m_x != -1) || (m_y != -1))
406 gtk_widget_set_uposition( m_widget, m_x, m_y );
407
408 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
409
410 // we cannot set MWM hints and icons before the widget has
411 // been realized, so we do this directly after realization
412 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
413 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
414
415 // the only way to get the window size is to connect to this event
416 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
417 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
418
419 // map and unmap for iconized state
420 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
421 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
422 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
423 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
424
425 // the only way to get the window size is to connect to this event
426 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
427 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
428
429 // disable native tab traversal
430 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
431 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
432
433 // decorations
434 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
435 {
436 m_gdkDecor = 0;
437 m_gdkFunc = 0;
438 }
439 else
440 {
441 m_gdkDecor = (long) GDK_DECOR_BORDER;
442 m_gdkFunc = (long) GDK_FUNC_MOVE;
443
444 // All this is for Motif Window Manager "hints" and is supposed to be
445 // recognized by other WMs as well.
446 if ((style & wxCAPTION) != 0)
447 m_gdkDecor |= GDK_DECOR_TITLE;
448 if ((style & wxSYSTEM_MENU) != 0)
449 {
450 m_gdkFunc |= GDK_FUNC_CLOSE;
451 m_gdkDecor |= GDK_DECOR_MENU;
452 }
453 if ((style & wxMINIMIZE_BOX) != 0)
454 {
455 m_gdkFunc |= GDK_FUNC_MINIMIZE;
456 m_gdkDecor |= GDK_DECOR_MINIMIZE;
457 }
458 if ((style & wxMAXIMIZE_BOX) != 0)
459 {
460 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
461 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
462 }
463 if ((style & wxRESIZE_BORDER) != 0)
464 {
465 m_gdkFunc |= GDK_FUNC_RESIZE;
466 m_gdkDecor |= GDK_DECOR_RESIZEH;
467 }
468 }
469
470 return TRUE;
471 }
472
473 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
474 {
475 m_isBeingDeleted = TRUE;
476
477 // it may also be GtkScrolledWindow in the case of an MDI child
478 if (GTK_IS_WINDOW(m_widget))
479 {
480 gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
481 }
482
483 wxTopLevelWindows.DeleteObject( this );
484
485 if (wxTheApp->GetTopWindow() == this)
486 wxTheApp->SetTopWindow( (wxWindow*) NULL );
487
488 if ((wxTopLevelWindows.Number() == 0) &&
489 (wxTheApp->GetExitOnFrameDelete()))
490 {
491 wxTheApp->ExitMainLoop();
492 }
493 }
494
495 bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
496 {
497 if (show == m_fsIsShowing) return FALSE; // return what?
498
499 m_fsIsShowing = show;
500
501 if (show)
502 {
503 m_fsSaveGdkFunc = m_gdkFunc;
504 m_fsSaveGdkDecor = m_gdkDecor;
505 m_fsSaveFlag = style;
506 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
507 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
508
509 gtk_widget_hide( m_widget );
510 gtk_widget_unrealize( m_widget );
511
512 m_gdkDecor = (long) GDK_DECOR_BORDER;
513 m_gdkFunc = (long) GDK_FUNC_MOVE;
514
515 int x;
516 int y;
517 wxDisplaySize( &x, &y );
518 SetSize( 0, 0, x, y );
519
520 gtk_widget_realize( m_widget );
521 gtk_widget_show( m_widget );
522 }
523 else
524 {
525 gtk_widget_hide( m_widget );
526 gtk_widget_unrealize( m_widget );
527
528 m_gdkFunc = m_fsSaveGdkFunc;
529 m_gdkDecor = m_fsSaveGdkDecor;
530
531 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
532
533 gtk_widget_realize( m_widget );
534 gtk_widget_show( m_widget );
535 }
536
537 return TRUE;
538 }
539
540 // ----------------------------------------------------------------------------
541 // overridden wxWindow methods
542 // ----------------------------------------------------------------------------
543
544 bool wxTopLevelWindowGTK::Show( bool show )
545 {
546 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
547
548 if (show && !m_sizeSet)
549 {
550 /* by calling GtkOnSize here, we don't have to call
551 either after showing the frame, which would entail
552 much ugly flicker or from within the size_allocate
553 handler, because GTK 1.1.X forbids that. */
554
555 GtkOnSize( m_x, m_y, m_width, m_height );
556 }
557
558 return wxWindow::Show( show );
559 }
560
561 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
562 {
563 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
564 }
565
566 void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
567 {
568 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
569
570 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
571 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
572
573 // avoid recursions
574 if (m_resizing)
575 return;
576 m_resizing = TRUE;
577
578 int old_x = m_x;
579 int old_y = m_y;
580
581 int old_width = m_width;
582 int old_height = m_height;
583
584 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
585 {
586 if (x != -1) m_x = x;
587 if (y != -1) m_y = y;
588 if (width != -1) m_width = width;
589 if (height != -1) m_height = height;
590 }
591 else
592 {
593 m_x = x;
594 m_y = y;
595 m_width = width;
596 m_height = height;
597 }
598
599 /*
600 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
601 {
602 if (width == -1) m_width = 80;
603 }
604
605 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
606 {
607 if (height == -1) m_height = 26;
608 }
609 */
610
611 int minWidth = GetMinWidth(),
612 minHeight = GetMinHeight(),
613 maxWidth = GetMaxWidth(),
614 maxHeight = GetMaxHeight();
615
616 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
617 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
618 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
619 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
620
621 if ((m_x != -1) || (m_y != -1))
622 {
623 if ((m_x != old_x) || (m_y != old_y))
624 {
625 gtk_widget_set_uposition( m_widget, m_x, m_y );
626 }
627 }
628
629 if ((m_width != old_width) || (m_height != old_height))
630 {
631 if (m_widget->window)
632 gdk_window_resize( m_widget->window, m_width, m_height );
633 else
634 gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height );
635
636 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
637 done either directly before the frame is shown or in idle time
638 so that different calls to SetSize() don't lead to flicker. */
639 m_sizeSet = FALSE;
640 }
641
642 m_resizing = FALSE;
643 }
644
645 void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
646 {
647 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
648
649 wxWindow::DoGetClientSize( width, height );
650 if (height)
651 {
652 // mini edge
653 *height -= m_miniEdge*2 + m_miniTitle;
654 }
655 if (width)
656 {
657 *width -= m_miniEdge*2;
658 }
659 }
660
661 void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
662 {
663 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
664
665 DoSetSize(-1, -1,
666 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
667 }
668
669 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
670 int width, int height )
671 {
672 // due to a bug in gtk, x,y are always 0
673 // m_x = x;
674 // m_y = y;
675
676 // avoid recursions
677 if (m_resizing) return;
678 m_resizing = TRUE;
679
680 if ( m_wxwindow == NULL ) return;
681
682 m_width = width;
683 m_height = height;
684
685 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
686 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
687 set in wxFrame::Create so it is used to check what kind of frame we
688 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
689 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
690 importantly) m_mainWidget */
691
692 int minWidth = GetMinWidth(),
693 minHeight = GetMinHeight(),
694 maxWidth = GetMaxWidth(),
695 maxHeight = GetMaxHeight();
696
697 if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
698 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
699 if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
700 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
701
702 if (m_mainWidget)
703 {
704 // set size hints
705 gint flag = 0; // GDK_HINT_POS;
706 if ((minWidth != -1) || (minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
707 if ((maxWidth != -1) || (maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
708 GdkGeometry geom;
709 geom.min_width = minWidth;
710 geom.min_height = minHeight;
711 geom.max_width = maxWidth;
712 geom.max_height = maxHeight;
713 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
714 (GtkWidget*) NULL,
715 &geom,
716 (GdkWindowHints) flag );
717
718 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
719 * menubar, the toolbar and the client area, which is represented by
720 * m_wxwindow.
721 * this hurts in the eye, but I don't want to call SetSize()
722 * because I don't want to call any non-native functions here. */
723
724 int client_x = m_miniEdge;
725 int client_y = m_miniEdge + m_miniTitle;
726 int client_w = m_width - 2*m_miniEdge;
727 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
728 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
729 m_wxwindow,
730 client_x, client_y, client_w, client_h );
731 }
732 else
733 {
734 // If there is no m_mainWidget between m_widget and m_wxwindow there
735 // is no need to set the size or position of m_wxwindow.
736 }
737
738 m_sizeSet = TRUE;
739
740 // send size event to frame
741 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
742 event.SetEventObject( this );
743 GetEventHandler()->ProcessEvent( event );
744
745 m_resizing = FALSE;
746 }
747
748 void wxTopLevelWindowGTK::OnInternalIdle()
749 {
750 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
751 {
752 GtkOnSize( m_x, m_y, m_width, m_height );
753
754 // we'll come back later
755 if (g_isIdle)
756 wxapp_install_idle_handler();
757 return;
758 }
759
760 // set the focus if not done yet and if we can already do it
761 if ( GTK_WIDGET_REALIZED(m_wxwindow) )
762 {
763 if ( g_delayedFocus &&
764 wxGetTopLevelParent((wxWindow*)g_delayedFocus) == this )
765 {
766 g_delayedFocus->SetFocus();
767 g_delayedFocus = NULL;
768 }
769 }
770
771 wxWindow::OnInternalIdle();
772 }
773
774 // ----------------------------------------------------------------------------
775 // frame title/icon
776 // ----------------------------------------------------------------------------
777
778 void wxTopLevelWindowGTK::SetTitle( const wxString &title )
779 {
780 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
781
782 m_title = title;
783 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
784 }
785
786 void wxTopLevelWindowGTK::DoSetIcon( const wxIcon &icon )
787 {
788 if ( !icon.Ok() )
789 return;
790
791 if (!m_widget->window)
792 return;
793
794 wxMask *mask = icon.GetMask();
795 GdkBitmap *bm = (GdkBitmap *) NULL;
796 if (mask) bm = mask->GetBitmap();
797
798 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
799 }
800
801 void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
802 {
803 SetIcons( wxIconBundle( icon ) );
804 }
805
806 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
807 {
808 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
809 GdkWindow* window = m_widget->window;
810
811 wxTopLevelWindowBase::SetIcons( icons );
812
813 DoSetIcon( icons.GetIcon( -1 ) );
814 if ( window )
815 {
816 wxSetIconsX11( (WXDisplay*)GDK_WINDOW_XDISPLAY( window ),
817 (WXWindow)GDK_WINDOW_XWINDOW( window ), icons );
818 }
819 }
820
821 // ----------------------------------------------------------------------------
822 // frame state: maximized/iconized/normal
823 // ----------------------------------------------------------------------------
824
825 void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
826 {
827 wxFAIL_MSG( _T("not implemented") );
828 }
829
830 bool wxTopLevelWindowGTK::IsMaximized() const
831 {
832 // wxFAIL_MSG( _T("not implemented") );
833
834 // This is an approximation
835 return FALSE;
836 }
837
838 void wxTopLevelWindowGTK::Restore()
839 {
840 wxFAIL_MSG( _T("not implemented") );
841 }
842
843 void wxTopLevelWindowGTK::Iconize( bool iconize )
844 {
845 if (iconize)
846 {
847 GdkWindow *window = m_widget->window;
848
849 // you should do it later, for example from OnCreate() handler
850 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
851
852 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
853 GDK_WINDOW_XWINDOW( window ),
854 DefaultScreen( GDK_DISPLAY() ) );
855 }
856 }
857
858 bool wxTopLevelWindowGTK::IsIconized() const
859 {
860 return m_isIconized;
861 }
862
863 void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
864 {
865 if ( iconize != m_isIconized )
866 {
867 m_isIconized = iconize;
868 (void)SendIconizeEvent(iconize);
869 }
870 }
871