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