]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/toplevel.cpp
oops, reverted wrong code
[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_fsSaveGdkFunc = m_gdkFunc;
528 m_fsSaveGdkDecor = m_gdkDecor;
529 m_fsSaveFlag = style;
530 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
531 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
532
533 gtk_widget_hide( m_widget );
534 gtk_widget_unrealize( m_widget );
535
536 m_gdkDecor = (long) GDK_DECOR_BORDER;
537 m_gdkFunc = (long) GDK_FUNC_MOVE;
538
539 int x;
540 int y;
541 wxDisplaySize( &x, &y );
542 SetSize( 0, 0, x, y );
543
544 gtk_widget_realize( m_widget );
545 gtk_widget_show( m_widget );
546 }
547 else
548 {
549 gtk_widget_hide( m_widget );
550 gtk_widget_unrealize( m_widget );
551
552 m_gdkFunc = m_fsSaveGdkFunc;
553 m_gdkDecor = m_fsSaveGdkDecor;
554
555 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
556
557 gtk_widget_realize( m_widget );
558 gtk_widget_show( m_widget );
559 }
560
561 return TRUE;
562 }
563
564 // ----------------------------------------------------------------------------
565 // overridden wxWindow methods
566 // ----------------------------------------------------------------------------
567
568 bool wxTopLevelWindowGTK::Show( bool show )
569 {
570 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
571
572 if (show && !m_sizeSet)
573 {
574 /* by calling GtkOnSize here, we don't have to call
575 either after showing the frame, which would entail
576 much ugly flicker or from within the size_allocate
577 handler, because GTK 1.1.X forbids that. */
578
579 GtkOnSize( m_x, m_y, m_width, m_height );
580 }
581
582 return wxWindow::Show( show );
583 }
584
585 void wxTopLevelWindowGTK::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
586 {
587 wxFAIL_MSG( wxT("DoMoveWindow called for wxTopLevelWindowGTK") );
588 }
589
590 void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags )
591 {
592 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
593
594 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
595 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
596
597 /* avoid recursions */
598 if (m_resizing)
599 return;
600 m_resizing = TRUE;
601
602 int old_x = m_x;
603 int old_y = m_y;
604
605 int old_width = m_width;
606 int old_height = m_height;
607
608 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
609 {
610 if (x != -1) m_x = x;
611 if (y != -1) m_y = y;
612 if (width != -1) m_width = width;
613 if (height != -1) m_height = height;
614 }
615 else
616 {
617 m_x = x;
618 m_y = y;
619 m_width = width;
620 m_height = height;
621 }
622
623 /*
624 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
625 {
626 if (width == -1) m_width = 80;
627 }
628
629 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
630 {
631 if (height == -1) m_height = 26;
632 }
633 */
634
635 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
636 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
637 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
638 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
639
640 if ((m_x != -1) || (m_y != -1))
641 {
642 if ((m_x != old_x) || (m_y != old_y))
643 {
644 gtk_widget_set_uposition( m_widget, m_x, m_y );
645 }
646 }
647
648 if ((m_width != old_width) || (m_height != old_height))
649 {
650 gtk_widget_set_usize( m_widget, m_width, m_height );
651
652 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
653 done either directly before the frame is shown or in idle time
654 so that different calls to SetSize() don't lead to flicker. */
655 m_sizeSet = FALSE;
656 }
657
658 m_resizing = FALSE;
659 }
660
661 void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const
662 {
663 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
664
665 wxWindow::DoGetClientSize( width, height );
666 if (height)
667 {
668 /* mini edge */
669 *height -= m_miniEdge*2 + m_miniTitle;
670 }
671 if (width)
672 {
673 *width -= m_miniEdge*2;
674 }
675 }
676
677 void wxTopLevelWindowGTK::DoSetClientSize( int width, int height )
678 {
679 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
680
681 DoSetSize(-1, -1,
682 width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0);
683 }
684
685 void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
686 int width, int height )
687 {
688 // due to a bug in gtk, x,y are always 0
689 // m_x = x;
690 // m_y = y;
691
692 /* avoid recursions */
693 if (m_resizing) return;
694 m_resizing = TRUE;
695
696 if ( m_wxwindow == NULL ) return;
697
698 m_width = width;
699 m_height = height;
700
701 /* wxMDIChildFrame derives from wxFrameGTK but it _is_ a wxWindow as it uses
702 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
703 set in wxFrameGTK::Create so it is used to check what kind of frame we
704 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
705 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
706 importantly) m_mainWidget */
707
708 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
709 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
710 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
711 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
712
713 if (m_mainWidget)
714 {
715 /* set size hints */
716 gint flag = 0; // GDK_HINT_POS;
717 if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
718 if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
719 GdkGeometry geom;
720 geom.min_width = m_minWidth;
721 geom.min_height = m_minHeight;
722 geom.max_width = m_maxWidth;
723 geom.max_height = m_maxHeight;
724 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
725 (GtkWidget*) NULL,
726 &geom,
727 (GdkWindowHints) flag );
728
729 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
730 * menubar, the toolbar and the client area, which is represented by
731 * m_wxwindow.
732 * this hurts in the eye, but I don't want to call SetSize()
733 * because I don't want to call any non-native functions here. */
734
735 int client_x = m_miniEdge;
736 int client_y = m_miniEdge + m_miniTitle;
737 int client_w = m_width - 2*m_miniEdge;
738 int client_h = m_height - 2*m_miniEdge - m_miniTitle;
739 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
740 m_wxwindow,
741 client_x, client_y, client_w, client_h );
742 }
743 else
744 {
745 /* if there is no m_mainWidget between m_widget and m_wxwindow there
746 is no need to set the size or position of m_wxwindow. */
747 }
748
749 m_sizeSet = TRUE;
750
751 // send size event to frame
752 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
753 event.SetEventObject( this );
754 GetEventHandler()->ProcessEvent( event );
755
756 m_resizing = FALSE;
757 }
758
759 void wxTopLevelWindowGTK::OnInternalIdle()
760 {
761 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
762 {
763 GtkOnSize( m_x, m_y, m_width, m_height );
764
765 // we'll come back later
766 if (g_isIdle)
767 wxapp_install_idle_handler();
768 return;
769 }
770
771 wxWindow::OnInternalIdle();
772 }
773
774
775 // ----------------------------------------------------------------------------
776 // frame title/icon
777 // ----------------------------------------------------------------------------
778
779 void wxTopLevelWindowGTK::SetTitle( const wxString &title )
780 {
781 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
782
783 m_title = title;
784 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
785 }
786
787 void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
788 {
789 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
790
791 wxTopLevelWindowBase::SetIcon(icon);
792
793 if ( !m_icon.Ok() )
794 return;
795
796 if (!m_widget->window)
797 return;
798
799 wxMask *mask = icon.GetMask();
800 GdkBitmap *bm = (GdkBitmap *) NULL;
801 if (mask) bm = mask->GetBitmap();
802
803 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
804 }
805
806 // ----------------------------------------------------------------------------
807 // frame state: maximized/iconized/normal
808 // ----------------------------------------------------------------------------
809
810 void wxTopLevelWindowGTK::Maximize(bool WXUNUSED(maximize))
811 {
812 wxFAIL_MSG( _T("not implemented") );
813 }
814
815 bool wxTopLevelWindowGTK::IsMaximized() const
816 {
817 // wxFAIL_MSG( _T("not implemented") );
818
819 // This is an approximation
820 return FALSE;
821 }
822
823 void wxTopLevelWindowGTK::Restore()
824 {
825 wxFAIL_MSG( _T("not implemented") );
826 }
827
828 void wxTopLevelWindowGTK::Iconize( bool iconize )
829 {
830 if (iconize)
831 {
832 GdkWindow *window = m_widget->window;
833
834 // you should do it later, for example from OnCreate() handler
835 wxCHECK_RET( window, _T("frame not created yet - can't iconize") );
836
837 XIconifyWindow( GDK_WINDOW_XDISPLAY( window ),
838 GDK_WINDOW_XWINDOW( window ),
839 DefaultScreen( GDK_DISPLAY() ) );
840 }
841 }
842
843 bool wxTopLevelWindowGTK::IsIconized() const
844 {
845 return m_isIconized;
846 }
847
848 void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
849 {
850 if ( iconize != m_isIconized )
851 {
852 m_isIconized = iconize;
853 (void)SendIconizeEvent(iconize);
854 }
855 }
856