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