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