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