]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/toplevel.cpp
Fixed wxToolbar95::FindToolForPosition
[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 #if (GTK_MINOR_VERSION > 0)
145 gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxTopLevelWindowGTK *win )
146 #else
147 gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxTopLevelWindowGTK *win )
148 #endif
149 {
150 if (g_isIdle)
151 wxapp_install_idle_handler();
152
153 if (!win->m_hasVMT)
154 return FALSE;
155
156 #if (GTK_MINOR_VERSION > 0)
157 int x = 0;
158 int y = 0;
159 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
160 win->m_x = x;
161 win->m_y = y;
162 #else
163 win->m_x = event->x;
164 win->m_y = event->y;
165 #endif
166
167 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
168 mevent.SetEventObject( win );
169 win->GetEventHandler()->ProcessEvent( mevent );
170
171 return FALSE;
172 }
173
174 //-----------------------------------------------------------------------------
175 // "realize" from m_widget
176 //-----------------------------------------------------------------------------
177
178 /* we cannot MWM hints and icons before the widget has been realized,
179 so we do this directly after realization */
180
181 static void
182 gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win )
183 {
184 if (g_isIdle)
185 wxapp_install_idle_handler();
186
187 /* All this is for Motif Window Manager "hints" and is supposed to be
188 recognized by other WM as well. Not tested. */
189 gdk_window_set_decorations(win->m_widget->window,
190 (GdkWMDecoration)win->m_gdkDecor);
191 gdk_window_set_functions(win->m_widget->window,
192 (GdkWMFunction)win->m_gdkFunc);
193
194 /* GTK's shrinking/growing policy */
195 if ((win->m_gdkFunc & GDK_FUNC_RESIZE) == 0)
196 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
197 else
198 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
199
200 /* reset the icon */
201 wxIcon iconOld = win->GetIcon();
202 if ( iconOld != wxNullIcon )
203 {
204 wxIcon icon( iconOld );
205 win->SetIcon( wxNullIcon );
206 win->SetIcon( icon );
207 }
208
209 /* we set the focus to the child that accepts the focus. this
210 doesn't really have to be done in "realize" but why not? */
211 wxWindowList::Node *node = win->GetChildren().GetFirst();
212 while (node)
213 {
214 wxWindow *child = node->GetData();
215 if (child->AcceptsFocus())
216 {
217 child->SetFocus();
218 break;
219 }
220
221 node = node->GetNext();
222 }
223 }
224
225 //-----------------------------------------------------------------------------
226 // "map_event" from m_widget
227 //-----------------------------------------------------------------------------
228
229 static void
230 gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
231 GdkEvent * WXUNUSED(event),
232 wxTopLevelWindow *win )
233 {
234 win->SetIconizeState(FALSE);
235 }
236
237 //-----------------------------------------------------------------------------
238 // "unmap_event" from m_widget
239 //-----------------------------------------------------------------------------
240
241 static void
242 gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
243 GdkEvent * WXUNUSED(event),
244 wxTopLevelWindow *win )
245 {
246 win->SetIconizeState(TRUE);
247 }
248
249 //-----------------------------------------------------------------------------
250 // "expose_event" of m_client
251 //-----------------------------------------------------------------------------
252
253 static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
254 {
255 GtkPizza *pizza = GTK_PIZZA(widget);
256
257 gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
258 GTK_SHADOW_NONE, &gdk_event->area, win->m_widget, "base", 0, 0, -1, -1);
259
260 return TRUE;
261 }
262
263 //-----------------------------------------------------------------------------
264 // "draw" of m_client
265 //-----------------------------------------------------------------------------
266
267
268 static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
269 {
270 GtkPizza *pizza = GTK_PIZZA(widget);
271
272 gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
273 GTK_SHADOW_NONE, rect, win->m_widget, "base", 0, 0, -1, -1);
274 }
275
276 // ----------------------------------------------------------------------------
277 // wxTopLevelWindowGTK itself
278 // ----------------------------------------------------------------------------
279
280 //-----------------------------------------------------------------------------
281 // InsertChild for wxTopLevelWindowGTK
282 //-----------------------------------------------------------------------------
283
284 /* Callback for wxTopLevelWindowGTK. This very strange beast has to be used because
285 * C++ has no virtual methods in a constructor. We have to emulate a
286 * virtual function here as wxWindows requires different ways to insert
287 * a child in container classes. */
288
289 static void wxInsertChildInTopLevelWindow( wxTopLevelWindowGTK* parent, wxWindow* child )
290 {
291 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
292
293 if (!parent->m_insertInClientArea)
294 {
295 /* these are outside the client area */
296 wxTopLevelWindowGTK* frame = (wxTopLevelWindowGTK*) parent;
297 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
298 GTK_WIDGET(child->m_widget),
299 child->m_x,
300 child->m_y,
301 child->m_width,
302 child->m_height );
303 }
304 else
305 {
306 /* these are inside the client area */
307 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
308 GTK_WIDGET(child->m_widget),
309 child->m_x,
310 child->m_y,
311 child->m_width,
312 child->m_height );
313 }
314
315 /* resize on OnInternalIdle */
316 parent->GtkUpdateSize();
317 }
318
319 // ----------------------------------------------------------------------------
320 // wxTopLevelWindowGTK creation
321 // ----------------------------------------------------------------------------
322
323 void wxTopLevelWindowGTK::Init()
324 {
325 m_sizeSet = FALSE;
326 m_miniEdge = 0;
327 m_miniTitle = 0;
328 m_mainWidget = (GtkWidget*) NULL;
329 m_insertInClientArea = TRUE;
330 m_isFrame = TRUE;
331 m_isIconized = FALSE;
332 m_fsIsShowing = FALSE;
333 m_themeEnabled = TRUE;
334 m_gdkDecor = m_gdkFunc = 0;
335 }
336
337 bool wxTopLevelWindowGTK::Create( wxWindow *parent,
338 wxWindowID id,
339 const wxString& title,
340 const wxPoint& pos,
341 const wxSize& sizeOrig,
342 long style,
343 const wxString &name )
344 {
345 // always create a frame of some reasonable, even if arbitrary, size (at
346 // least for MSW compatibility)
347 wxSize size = sizeOrig;
348 if ( size.x == -1 || size.y == -1 )
349 {
350 wxSize sizeDpy = wxGetDisplaySize();
351 if ( size.x == -1 )
352 size.x = sizeDpy.x / 3;
353 if ( size.y == -1 )
354 size.y = sizeDpy.y / 5;
355 }
356
357 wxTopLevelWindows.Append( this );
358
359 m_needParent = FALSE;
360
361 if (!PreCreation( parent, pos, size ) ||
362 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
363 {
364 wxFAIL_MSG( wxT("wxTopLevelWindowGTK creation failed") );
365 return FALSE;
366 }
367
368 m_title = title;
369
370 m_insertCallback = (wxInsertChildFunction) wxInsertChildInTopLevelWindow;
371
372 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
373
374 if (style & wxFRAME_TOOL_WINDOW)
375 win_type = GTK_WINDOW_POPUP;
376
377 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
378 win_type = GTK_WINDOW_DIALOG;
379
380 m_widget = gtk_window_new( win_type );
381
382 if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget)))
383 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
384
385 if (!name.IsEmpty())
386 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
387
388 #ifdef __WXDEBUG__
389 debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name );
390 #endif
391
392 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
393 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
394
395 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
396 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
397
398 /* m_mainWidget holds the toolbar, the menubar and the client area */
399 m_mainWidget = gtk_pizza_new();
400 gtk_widget_show( m_mainWidget );
401 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
402 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
403
404 /* for m_mainWidget themes */
405 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
406 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
407 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
408 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
409
410 #ifdef __WXDEBUG__
411 debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name );
412 #endif
413
414 /* m_wxwindow only represents the client area without toolbar and menubar */
415 m_wxwindow = gtk_pizza_new();
416 gtk_widget_show( m_wxwindow );
417 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
418
419 #ifdef __WXDEBUG__
420 debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name );
421 #endif
422
423 /* we donm't allow the frame to get the focus as otherwise
424 the frame will grab it at arbitrary focus changes. */
425 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
426
427 if (m_parent) m_parent->AddChild( this );
428
429 /* the user resized the frame by dragging etc. */
430 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
431 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
432
433 PostCreation();
434
435 if ((m_x != -1) || (m_y != -1))
436 gtk_widget_set_uposition( m_widget, m_x, m_y );
437 gtk_widget_set_usize( m_widget, m_width, m_height );
438
439 /* we cannot set MWM hints and icons before the widget has
440 been realized, so we do this directly after realization */
441 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
442 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
443
444 /* the only way to get the window size is to connect to this event */
445 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
446 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
447
448 /* map and unmap for iconized state */
449 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
450 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
451 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
452 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
453
454 /* the only way to get the window size is to connect to this event */
455 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
456 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
457
458 /* disable native tab traversal */
459 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
460 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
461
462
463 /* decorations */
464 if ((m_miniEdge > 0) || (style & wxSIMPLE_BORDER) || (style & wxNO_BORDER))
465 {
466 m_gdkDecor = 0;
467 m_gdkFunc = 0;
468 }
469 else
470 {
471 m_gdkDecor = (long) GDK_DECOR_BORDER;
472 m_gdkFunc = (long) GDK_FUNC_MOVE;
473
474 // All this is for Motif Window Manager "hints" and is supposed to be
475 // recognized by other WM as well. Not tested.
476 if ((style & wxCAPTION) != 0)
477 m_gdkDecor |= GDK_DECOR_TITLE;
478 if ((style & wxSYSTEM_MENU) != 0)
479 {
480 m_gdkFunc |= GDK_FUNC_CLOSE;
481 m_gdkDecor |= GDK_DECOR_MENU;
482 }
483 if ((style & wxMINIMIZE_BOX) != 0)
484 {
485 m_gdkFunc |= GDK_FUNC_MINIMIZE;
486 m_gdkDecor |= GDK_DECOR_MINIMIZE;
487 }
488 if ((style & wxMAXIMIZE_BOX) != 0)
489 {
490 m_gdkFunc |= GDK_FUNC_MAXIMIZE;
491 m_gdkDecor |= GDK_DECOR_MAXIMIZE;
492 }
493 if ((style & wxRESIZE_BORDER) != 0)
494 {
495 m_gdkFunc |= GDK_FUNC_RESIZE;
496 m_gdkDecor |= GDK_DECOR_RESIZEH;
497 }
498 }
499
500 return TRUE;
501 }
502
503 wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
504 {
505 m_isBeingDeleted = TRUE;
506
507 wxTopLevelWindows.DeleteObject( this );
508
509 if (wxTheApp->GetTopWindow() == this)
510 wxTheApp->SetTopWindow( (wxWindow*) NULL );
511
512 if ((wxTopLevelWindows.Number() == 0) &&
513 (wxTheApp->GetExitOnFrameDelete()))
514 {
515 wxTheApp->ExitMainLoop();
516 }
517 }
518
519 bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
520 {
521 if (show == m_fsIsShowing) return FALSE; // return what?
522
523 m_fsIsShowing = show;
524
525 if (show)
526 {
527 m_fsSaveStyle = m_windowStyle;
528 m_fsSaveFlag = style;
529 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
530 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
531
532 gtk_widget_hide( m_widget );
533 gtk_widget_unrealize( m_widget );
534
535 m_windowStyle = wxSIMPLE_BORDER;
536
537 int x;
538 int y;
539 wxDisplaySize( &x, &y );
540 SetSize( 0, 0, x, y );
541
542 gtk_widget_realize( m_widget );
543 gtk_widget_show( m_widget );
544 }
545 else
546 {
547 gtk_widget_hide( m_widget );
548 gtk_widget_unrealize( m_widget );
549
550 m_windowStyle = m_fsSaveStyle;
551
552 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
553
554 gtk_widget_realize( m_widget );
555 gtk_widget_show( m_widget );
556 }
557
558 return TRUE;
559 }
560
561 // ----------------------------------------------------------------------------
562 // overridden wxWindow methods
563 // ----------------------------------------------------------------------------
564
565 bool wxTopLevelWindowGTK::Show( bool show )
566 {
567 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
568
569 if (show && !m_sizeSet)
570 {
571 /* by calling GtkOnSize here, we don't have to call
572 either after showing the frame, which would entail
573 much ugly flicker or from within the size_allocate
574 handler, because GTK 1.1.X forbids that. */
575
576 GtkOnSize( m_x, m_y, m_width, m_height );
577 }
578
579 return wxWindow::Show( show );
580 }
581
582 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
583 {
584 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
585 }
586
587 void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
588 {
589 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
590
591 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
592 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
593
594 /* avoid recursions */
595 if (m_resizing)
596 return;
597 m_resizing = TRUE;
598
599 int old_x = m_x;
600 int old_y = m_y;
601
602 int old_width = m_width;
603 int old_height = m_height;
604
605 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
606 {
607 if (x != -1) m_x = x;
608 if (y != -1) m_y = y;
609 if (width != -1) m_width = width;
610 if (height != -1) m_height = height;
611 }
612 else
613 {
614 m_x = x;
615 m_y = y;
616 m_width = width;
617 m_height = height;
618 }
619
620 /*
621 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
622 {
623 if (width == -1) m_width = 80;
624 }
625
626 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
627 {
628 if (height == -1) m_height = 26;
629 }
630 */
631
632 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
633 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
634 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
635 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
636
637 if ((m_x != -1) || (m_y != -1))
638 {
639 if ((m_x != old_x) || (m_y != old_y))
640 {
641 gtk_widget_set_uposition( m_widget, m_x, m_y );
642 }
643 }
644
645 if ((m_width != old_width) || (m_height != old_height))
646 {
647 gtk_widget_set_usize( 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 wxFrameGTK but it _is_ a wxWindow as it uses
699 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
700 set in wxFrameGTK::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