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