]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/frame.cpp
Fixed problem with CaptureMouse if cursor is null.
[wxWidgets.git] / src / gtk / frame.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: frame.cpp
3// Purpose:
4// Author: Robert Roebling
a81258be 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling
19717c50 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
7c0ea335
VZ
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
c801d85f 18#ifdef __GNUG__
fe4e9e6c 19 #pragma implementation "frame.h"
c801d85f
KB
20#endif
21
22#include "wx/frame.h"
23#include "wx/dialog.h"
24#include "wx/control.h"
25#include "wx/app.h"
cf4219e7 26#include "wx/menu.h"
dcf924a3 27#if wxUSE_TOOLBAR
7c0ea335 28 #include "wx/toolbar.h"
dcf924a3
RR
29#endif
30#if wxUSE_STATUSBAR
7c0ea335 31 #include "wx/statusbr.h"
dcf924a3 32#endif
362c6693 33#include "wx/dcclient.h"
83624f79 34
55703c91
RR
35#include <glib.h>
36#include <gdk/gdk.h>
37#include <gtk/gtk.h>
38#include <gdk/gdkkeysyms.h>
39#include <gdk/gdkx.h>
40
c801d85f
KB
41#include "wx/gtk/win_gtk.h"
42
7c0ea335 43// ----------------------------------------------------------------------------
2f2aa628 44// constants
7c0ea335 45// ----------------------------------------------------------------------------
2f2aa628 46
907789a0 47const int wxMENU_HEIGHT = 27;
c67daf87 48const int wxSTATUS_HEIGHT = 25;
41ca191f 49const int wxPLACE_HOLDER = 0;
c801d85f 50
7c0ea335 51// ----------------------------------------------------------------------------
acfd422a 52// idle system
7c0ea335 53// ----------------------------------------------------------------------------
acfd422a
RR
54
55extern void wxapp_install_idle_handler();
56extern bool g_isIdle;
2d68e1b4 57extern int g_openDialogs;
acfd422a 58
7c0ea335
VZ
59// ----------------------------------------------------------------------------
60// event tables
61// ----------------------------------------------------------------------------
62
63IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
64
65// ----------------------------------------------------------------------------
2f2aa628 66// data
7c0ea335 67// ----------------------------------------------------------------------------
2f2aa628 68
c801d85f
KB
69extern wxList wxPendingDelete;
70
7c0ea335 71// ----------------------------------------------------------------------------
2e563988 72// debug
7c0ea335 73// ----------------------------------------------------------------------------
2e563988
RR
74
75#ifdef __WXDEBUG__
76
77extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
78
79#endif
80
7c0ea335
VZ
81// ============================================================================
82// implementation
83// ============================================================================
84
85// ----------------------------------------------------------------------------
86// GTK callbacks
87// ----------------------------------------------------------------------------
88
69ffe1d2
RR
89//-----------------------------------------------------------------------------
90// "focus" from m_window
91//-----------------------------------------------------------------------------
92
93static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
94{
95 if (g_isIdle)
96 wxapp_install_idle_handler();
97
98 // This disables GTK's tab traversal
99 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
100 return TRUE;
101}
102
c801d85f 103//-----------------------------------------------------------------------------
2f2aa628 104// "size_allocate"
c801d85f 105//-----------------------------------------------------------------------------
c801d85f 106
2f2aa628 107static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
ed7a557b 108{
88ac883a 109 if (g_isIdle)
121a3581 110 wxapp_install_idle_handler();
acfd422a 111
54517652
RR
112 if (!win->m_hasVMT)
113 return;
8bbe427f 114
121a3581
RR
115 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
116 {
54517652
RR
117/*
118 wxPrintf( "OnSize from " );
119 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
120 wxPrintf( win->GetClassInfo()->GetClassName() );
121 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
122 (int)alloc->y,
123 (int)alloc->width,
124 (int)alloc->height );
125*/
7beba2fc 126
121a3581
RR
127 win->m_width = alloc->width;
128 win->m_height = alloc->height;
8cb9f0d0 129 win->m_queuedFullRedraw = TRUE;
5b8a521e 130 win->GtkUpdateSize();
121a3581 131 }
362c6693 132}
c801d85f
KB
133
134//-----------------------------------------------------------------------------
2f2aa628
RR
135// "delete_event"
136//-----------------------------------------------------------------------------
c801d85f 137
2f2aa628 138static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
ed7a557b 139{
88ac883a 140 if (g_isIdle)
121a3581 141 wxapp_install_idle_handler();
ed7a557b 142
a56fcaaf 143 if ((g_openDialogs == 0) && (win->IsEnabled()))
2d68e1b4 144 win->Close();
c801d85f 145
fb1585ae 146 return TRUE;
362c6693 147}
c801d85f 148
16bcc879
RR
149//-----------------------------------------------------------------------------
150// "child_attached" of menu bar
151//-----------------------------------------------------------------------------
152
153static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
154{
a2053b27 155 if (!win->m_hasVMT) return;
88ac883a 156
16bcc879 157 win->m_menuBarDetached = FALSE;
5b8a521e 158 win->GtkUpdateSize();
16bcc879
RR
159}
160
161//-----------------------------------------------------------------------------
162// "child_detached" of menu bar
163//-----------------------------------------------------------------------------
164
165static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
166{
a2053b27 167 if (!win->m_hasVMT) return;
88ac883a 168
16bcc879 169 win->m_menuBarDetached = TRUE;
5b8a521e 170 win->GtkUpdateSize();
16bcc879
RR
171}
172
88ac883a 173#if wxUSE_TOOLBAR
16bcc879
RR
174//-----------------------------------------------------------------------------
175// "child_attached" of tool bar
176//-----------------------------------------------------------------------------
177
178static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
179{
a2053b27 180 if (!win->m_hasVMT) return;
88ac883a 181
16bcc879 182 win->m_toolBarDetached = FALSE;
88ac883a 183
5b8a521e 184 win->GtkUpdateSize();
16bcc879
RR
185}
186
187//-----------------------------------------------------------------------------
188// "child_detached" of tool bar
189//-----------------------------------------------------------------------------
190
5e0201ea 191static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
16bcc879 192{
88ac883a 193 if (g_isIdle)
801aa178 194 wxapp_install_idle_handler();
acfd422a 195
a2053b27 196 if (!win->m_hasVMT) return;
88ac883a 197
16bcc879 198 win->m_toolBarDetached = TRUE;
5b8a521e 199 win->GtkUpdateSize();
16bcc879 200}
88ac883a 201#endif // wxUSE_TOOLBAR
16bcc879 202
47908e25 203//-----------------------------------------------------------------------------
2f2aa628
RR
204// "configure_event"
205//-----------------------------------------------------------------------------
47908e25 206
7beba2fc 207static gint
2d68e1b4 208#if (GTK_MINOR_VERSION > 0)
c693edf3
RR
209gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxFrame *win )
210#else
211gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxFrame *win )
212#endif
47908e25 213{
7beba2fc 214 if (g_isIdle)
121a3581 215 wxapp_install_idle_handler();
acfd422a 216
7c0ea335 217 if (!win->m_hasVMT)
2d68e1b4 218 return FALSE;
81855216 219
2d68e1b4 220#if (GTK_MINOR_VERSION > 0)
dfc3d7e0
RR
221 int x = 0;
222 int y = 0;
223 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
dfc3d7e0
RR
224 win->m_x = x;
225 win->m_y = y;
c693edf3
RR
226#else
227 win->m_x = event->x;
228 win->m_y = event->y;
229#endif
8bbe427f 230
a2053b27 231 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
36b3b54a
RR
232 mevent.SetEventObject( win );
233 win->GetEventHandler()->ProcessEvent( mevent );
234
fb1585ae 235 return FALSE;
362c6693 236}
47908e25 237
2b07d713
RR
238//-----------------------------------------------------------------------------
239// "realize" from m_widget
240//-----------------------------------------------------------------------------
241
88ac883a 242/* we cannot MWM hints and icons before the widget has been realized,
2b07d713
RR
243 so we do this directly after realization */
244
88ac883a 245static gint
2e5c594e 246gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
2b07d713 247{
88ac883a 248 if (g_isIdle)
121a3581 249 wxapp_install_idle_handler();
acfd422a 250
80629c8b 251 if ((win->m_miniEdge > 0) || (win->HasFlag(wxSIMPLE_BORDER)))
15b24b14 252 {
80629c8b 253 /* This is a mini-frame or a borderless frame. */
81855216
RR
254 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)0 );
255 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)0 );
15b24b14 256 }
81855216 257 else
aa64626e 258 {
81855216
RR
259 /* All this is for Motif Window Manager "hints" and is supposed to be
260 recognized by other WM as well. Not tested. */
261 long decor = (long) GDK_DECOR_BORDER;
262 long func = (long) GDK_FUNC_MOVE;
263
264 if ((win->GetWindowStyle() & wxCAPTION) != 0)
265 decor |= GDK_DECOR_TITLE;
266 if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
267 {
268 decor |= GDK_DECOR_MENU;
269 func |= GDK_FUNC_CLOSE;
270 }
271 if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
272 {
273 func |= GDK_FUNC_MINIMIZE;
274 decor |= GDK_DECOR_MINIMIZE;
275 }
276 if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
277 {
278 func |= GDK_FUNC_MAXIMIZE;
279 decor |= GDK_DECOR_MAXIMIZE;
280 }
281 if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
282 {
283 func |= GDK_FUNC_RESIZE;
284 decor |= GDK_DECOR_RESIZEH;
285 }
286
287 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
288 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
aa64626e
KB
289 }
290
2b07d713 291 /* GTK's shrinking/growing policy */
f03fc89f 292 if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
a2053b27 293 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
2b07d713 294 else
a2053b27 295 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
88ac883a 296
58dea4b0 297 /* reset the icon */
7c0ea335
VZ
298 wxIcon iconOld = win->GetIcon();
299 if ( iconOld != wxNullIcon )
58dea4b0 300 {
7c0ea335
VZ
301 wxIcon icon( iconOld );
302 win->SetIcon( wxNullIcon );
f03fc89f 303 win->SetIcon( icon );
58dea4b0 304 }
88ac883a 305
2e563988
RR
306 /* we set the focus to the child that accepts the focus. this
307 doesn't really have to be done in "realize" but why not? */
f03fc89f 308 wxWindowList::Node *node = win->GetChildren().GetFirst();
2e563988
RR
309 while (node)
310 {
f03fc89f
VZ
311 wxWindow *child = node->GetData();
312 if (child->AcceptsFocus())
313 {
314 child->SetFocus();
315 break;
316 }
88ac883a 317
f03fc89f 318 node = node->GetNext();
2e563988 319 }
88ac883a 320
227e5e99
RR
321 return FALSE;
322}
88ac883a 323
7c0ea335
VZ
324// ----------------------------------------------------------------------------
325// wxFrame itself
326// ----------------------------------------------------------------------------
327
f362b96d
RR
328//-----------------------------------------------------------------------------
329// InsertChild for wxFrame
330//-----------------------------------------------------------------------------
331
332/* Callback for wxFrame. This very strange beast has to be used because
333 * C++ has no virtual methods in a constructor. We have to emulate a
334 * virtual function here as wxWindows requires different ways to insert
335 * a child in container classes. */
336
6bc8a1c8 337static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
f362b96d 338{
5fd11f09 339 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
7beba2fc 340
6bc8a1c8 341 if (!parent->m_insertInClientArea)
f362b96d
RR
342 {
343 /* these are outside the client area */
f03fc89f 344 wxFrame* frame = (wxFrame*) parent;
da048e3d 345 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
a2053b27
RR
346 GTK_WIDGET(child->m_widget),
347 child->m_x,
348 child->m_y,
349 child->m_width,
350 child->m_height );
88ac883a 351
caf51f95 352#if wxUSE_TOOLBAR_NATIVE
f03fc89f
VZ
353 /* we connect to these events for recalculating the client area
354 space when the toolbar is floating */
355 if (wxIS_KIND_OF(child,wxToolBar))
356 {
357 wxToolBar *toolBar = (wxToolBar*) child;
358 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
359 {
a2053b27 360 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
41ca191f 361 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
88ac883a 362
a2053b27 363 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
41ca191f 364 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
f03fc89f
VZ
365 }
366 }
88ac883a 367#endif // wxUSE_TOOLBAR
f362b96d
RR
368 }
369 else
370 {
371 /* these are inside the client area */
da048e3d 372 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
a2053b27
RR
373 GTK_WIDGET(child->m_widget),
374 child->m_x,
375 child->m_y,
376 child->m_width,
377 child->m_height );
f362b96d
RR
378 }
379
f362b96d 380 /* resize on OnInternalIdle */
5b8a521e 381 parent->GtkUpdateSize();
f362b96d
RR
382}
383
7c0ea335
VZ
384// ----------------------------------------------------------------------------
385// wxFrame creation
386// ----------------------------------------------------------------------------
c801d85f 387
ddb6bc71 388void wxFrame::Init()
c801d85f 389{
fb1585ae 390 m_sizeSet = FALSE;
b2b3ccc5
RR
391 m_miniEdge = 0;
392 m_miniTitle = 0;
ab2b3dd4 393 m_mainWidget = (GtkWidget*) NULL;
16bcc879
RR
394 m_menuBarDetached = FALSE;
395 m_toolBarDetached = FALSE;
6bc8a1c8 396 m_insertInClientArea = TRUE;
8cb9f0d0 397 m_isFrame = FALSE;
362c6693 398}
c801d85f 399
7c0ea335
VZ
400bool wxFrame::Create( wxWindow *parent,
401 wxWindowID id,
402 const wxString &title,
403 const wxPoint &pos,
404 const wxSize &size,
405 long style,
406 const wxString &name )
c801d85f 407{
a802c3a1 408 wxTopLevelWindows.Append( this );
8bbe427f 409
fb1585ae 410 m_needParent = FALSE;
8cb9f0d0 411 m_isFrame = TRUE;
ed7a557b 412
4dcaf11a
RR
413 if (!PreCreation( parent, pos, size ) ||
414 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
415 {
223d09f6 416 wxFAIL_MSG( wxT("wxFrame creation failed") );
7beba2fc 417 return FALSE;
4dcaf11a 418 }
c801d85f 419
fb1585ae 420 m_title = title;
88ac883a 421
6bc8a1c8 422 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
ed7a557b 423
faecf4cb 424 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
8bbe427f 425
fb1585ae 426 m_widget = gtk_window_new( win_type );
88ac883a 427
80629c8b
RR
428 if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget)))
429 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
430
de1c750f
RR
431 if (!name.IsEmpty())
432 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
8bbe427f 433
2e563988 434#ifdef __WXDEBUG__
223d09f6 435 debug_focus_in( m_widget, wxT("wxFrame::m_widget"), name );
2e563988
RR
436#endif
437
ed9b9841 438 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
fb1585ae 439 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ed7a557b 440
fb1585ae
RR
441 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
442 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
ed7a557b 443
f362b96d 444 /* m_mainWidget holds the toolbar, the menubar and the client area */
da048e3d 445 m_mainWidget = gtk_pizza_new();
f362b96d
RR
446 gtk_widget_show( m_mainWidget );
447 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
448 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
88ac883a 449
2e563988 450#ifdef __WXDEBUG__
223d09f6 451 debug_focus_in( m_mainWidget, wxT("wxFrame::m_mainWidget"), name );
2e563988
RR
452#endif
453
f362b96d 454 /* m_wxwindow only represents the client area without toolbar and menubar */
da048e3d 455 m_wxwindow = gtk_pizza_new();
fb1585ae 456 gtk_widget_show( m_wxwindow );
f362b96d 457 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
88ac883a 458
2e563988 459#ifdef __WXDEBUG__
223d09f6 460 debug_focus_in( m_wxwindow, wxT("wxFrame::m_wxwindow"), name );
2e563988
RR
461#endif
462
463 /* we donm't allow the frame to get the focus as otherwise
464 the frame will grabit at arbitrary fcous changes. */
465 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
ed7a557b 466
de8113d9
RR
467 if (m_parent) m_parent->AddChild( this );
468
54517652
RR
469 /* the user resized the frame by dragging etc. */
470 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
471 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
472
de8113d9
RR
473 PostCreation();
474
15909a16
RR
475 if ((m_x != -1) || (m_y != -1))
476 gtk_widget_set_uposition( m_widget, m_x, m_y );
477 gtk_widget_set_usize( m_widget, m_width, m_height );
478
58dea4b0 479 /* we cannot set MWM hints and icons before the widget has
2b07d713
RR
480 been realized, so we do this directly after realization */
481 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
f03fc89f 482 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
88ac883a 483
ab2b3dd4 484 /* the only way to get the window size is to connect to this event */
fb1585ae
RR
485 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
486 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
8bbe427f 487
69ffe1d2
RR
488 /* disable native tab traversal */
489 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
490 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
491
fb1585ae 492 return TRUE;
362c6693 493}
c801d85f 494
19717c50 495wxFrame::~wxFrame()
c801d85f 496{
31c6b4fc 497 m_isBeingDeleted = TRUE;
88ac883a 498
7c0ea335 499 DeleteAllBars();
ed7a557b 500
fb1585ae 501 wxTopLevelWindows.DeleteObject( this );
2b854a32 502
0d2a2b60 503 if (wxTheApp->GetTopWindow() == this)
0d2a2b60 504 wxTheApp->SetTopWindow( (wxWindow*) NULL );
2b854a32 505
f59d80ca
RR
506 if ((wxTopLevelWindows.Number() == 0) &&
507 (wxTheApp->GetExitOnFrameDelete()))
508 {
0d2a2b60 509 wxTheApp->ExitMainLoop();
f59d80ca 510 }
362c6693 511}
ed7a557b 512
7c0ea335
VZ
513// ----------------------------------------------------------------------------
514// overridden wxWindow methods
515// ----------------------------------------------------------------------------
516
debe6624 517bool wxFrame::Show( bool show )
c801d85f 518{
223d09f6 519 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 520
35178437 521 if (show && !m_sizeSet)
fb1585ae 522 {
e27ce4e9
RR
523 /* by calling GtkOnSize here, we don't have to call
524 either after showing the frame, which would entail
f362b96d 525 much ugly flicker or from within the size_allocate
e27ce4e9 526 handler, because GTK 1.1.X forbids that. */
8bbe427f 527
35178437 528 GtkOnSize( m_x, m_y, m_width, m_height );
fb1585ae 529 }
8bbe427f 530
fb1585ae 531 return wxWindow::Show( show );
362c6693 532}
c801d85f 533
23efdd02
RR
534void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
535{
536 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
537}
538
bfc6fde4 539void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
903f689b 540{
223d09f6 541 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 542
ab2b3dd4 543 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
223d09f6 544 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
88ac883a 545
ab2b3dd4 546 /* avoid recursions */
7c0ea335
VZ
547 if (m_resizing)
548 return;
fb1585ae
RR
549 m_resizing = TRUE;
550
551 int old_x = m_x;
552 int old_y = m_y;
7beba2fc 553
fb1585ae
RR
554 int old_width = m_width;
555 int old_height = m_height;
8bbe427f 556
85ad5eb5 557 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
fb1585ae
RR
558 {
559 if (x != -1) m_x = x;
560 if (y != -1) m_y = y;
561 if (width != -1) m_width = width;
562 if (height != -1) m_height = height;
563 }
564 else
565 {
566 m_x = x;
567 m_y = y;
568 m_width = width;
569 m_height = height;
570 }
571
11e1c70d 572/*
fb1585ae
RR
573 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
574 {
575 if (width == -1) m_width = 80;
576 }
577
578 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
579 {
580 if (height == -1) m_height = 26;
581 }
11e1c70d 582*/
8bbe427f 583
fb1585ae
RR
584 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
585 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
0c77152e
RR
586 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
587 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
fb1585ae
RR
588
589 if ((m_x != -1) || (m_y != -1))
590 {
8bbe427f 591 if ((m_x != old_x) || (m_y != old_y))
0138c2de 592 {
8487f887 593 gtk_widget_set_uposition( m_widget, m_x, m_y );
0138c2de 594 }
fb1585ae 595 }
8bbe427f 596
fb1585ae
RR
597 if ((m_width != old_width) || (m_height != old_height))
598 {
15909a16
RR
599 gtk_widget_set_usize( m_widget, m_width, m_height );
600
ab2b3dd4 601 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
f03fc89f
VZ
602 done either directly before the frame is shown or in idle time
603 so that different calls to SetSize() don't lead to flicker. */
de8113d9 604 m_sizeSet = FALSE;
fb1585ae 605 }
8bbe427f 606
fb1585ae 607 m_resizing = FALSE;
903f689b
RR
608}
609
f9241296 610void wxFrame::DoGetClientSize( int *width, int *height ) const
c801d85f 611{
223d09f6 612 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 613
f9241296 614 wxWindow::DoGetClientSize( width, height );
fb1585ae 615 if (height)
46dc76ba 616 {
41ca191f
RR
617 /* menu bar */
618 if (m_frameMenuBar)
f03fc89f 619 {
88ac883a 620 if (!m_menuBarDetached)
f03fc89f
VZ
621 (*height) -= wxMENU_HEIGHT;
622 else
623 (*height) -= wxPLACE_HOLDER;
624 }
88ac883a 625
dcf924a3 626#if wxUSE_STATUSBAR
f03fc89f 627 /* status bar */
fb1585ae 628 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
93fa69f8 629#endif // wxUSE_STATUSBAR
88ac883a 630
dcf924a3 631#if wxUSE_TOOLBAR
f03fc89f 632 /* tool bar */
fb1585ae
RR
633 if (m_frameToolBar)
634 {
93fa69f8 635 if (m_toolBarDetached)
f03fc89f 636 {
93fa69f8 637 *height -= wxPLACE_HOLDER;
f03fc89f
VZ
638 }
639 else
93fa69f8
VZ
640 {
641 int x, y;
642 m_frameToolBar->GetSize( &x, &y );
643 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
644 {
645 *width -= x;
646 }
647 else
648 {
649 *height -= y;
650 }
651 }
fb1585ae 652 }
93fa69f8 653#endif // wxUSE_TOOLBAR
88ac883a 654
f03fc89f 655 /* mini edge */
93fa69f8 656 *height -= m_miniEdge*2 + m_miniTitle;
b2b3ccc5
RR
657 }
658 if (width)
659 {
93fa69f8 660 *width -= m_miniEdge*2;
46dc76ba 661 }
362c6693 662}
c801d85f 663
bfc6fde4 664void wxFrame::DoSetClientSize( int width, int height )
b593568e 665{
223d09f6 666 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 667
41ca191f
RR
668 /* menu bar */
669 if (m_frameMenuBar)
f03fc89f 670 {
88ac883a 671 if (!m_menuBarDetached)
f03fc89f
VZ
672 height += wxMENU_HEIGHT;
673 else
674 height += wxPLACE_HOLDER;
675 }
88ac883a 676
dcf924a3 677#if wxUSE_STATUSBAR
f03fc89f 678 /* status bar */
41ca191f 679 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
dcf924a3 680#endif
88ac883a 681
dcf924a3 682#if wxUSE_TOOLBAR
f03fc89f 683 /* tool bar */
41ca191f
RR
684 if (m_frameToolBar)
685 {
93fa69f8 686 if (m_toolBarDetached)
f03fc89f 687 {
93fa69f8 688 height += wxPLACE_HOLDER;
f03fc89f
VZ
689 }
690 else
93fa69f8
VZ
691 {
692 int x, y;
693 m_frameToolBar->GetSize( &x, &y );
694 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
695 {
696 width += x;
697 }
698 else
699 {
700 height += y;
701 }
702 }
41ca191f 703 }
dcf924a3 704#endif
88ac883a 705
3017f78d 706 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
362c6693 707}
b593568e 708
7c0ea335
VZ
709void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
710 int width, int height )
c801d85f 711{
f5368809
RR
712 // due to a bug in gtk, x,y are always 0
713 // m_x = x;
714 // m_y = y;
715
ab2b3dd4 716 /* avoid recursions */
e52f60e6
RR
717 if (m_resizing) return;
718 m_resizing = TRUE;
8bbe427f 719
ab2b3dd4 720 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
223d09f6 721 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
88ac883a 722
f5368809
RR
723 m_width = width;
724 m_height = height;
7beba2fc 725
ab2b3dd4 726 /* space occupied by m_frameToolBar and m_frameMenuBar */
93fa69f8
VZ
727 int client_area_x_offset = 0,
728 client_area_y_offset = 0;
8bbe427f 729
ab2b3dd4
RR
730 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
731 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
732 set in wxFrame::Create so it is used to check what kind of frame we
733 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
734 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
735 importantly) m_mainWidget */
88ac883a 736
1f3c610d
RR
737 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
738 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
739 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
740 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
741
742 /* set size hints */
743 gint flag = 0; // GDK_HINT_POS;
744 if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
745 if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
746 GdkGeometry geom;
747 geom.min_width = m_minWidth;
748 geom.min_height = m_minHeight;
749 geom.max_width = m_maxWidth;
750 geom.max_height = m_maxHeight;
751 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
752 (GtkWidget*) NULL,
753 &geom,
754 (GdkWindowHints) flag );
755
ab2b3dd4 756 if (m_mainWidget)
f5368809 757 {
ab2b3dd4
RR
758
759 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
760 * menubar, the toolbar and the client area, which is represented by
761 * m_wxwindow.
762 * this hurts in the eye, but I don't want to call SetSize()
763 * because I don't want to call any non-native functions here. */
88ac883a 764
ab2b3dd4
RR
765 if (m_frameMenuBar)
766 {
767 int xx = m_miniEdge;
768 int yy = m_miniEdge + m_miniTitle;
769 int ww = m_width - 2*m_miniEdge;
41ca191f 770 int hh = wxMENU_HEIGHT;
f03fc89f 771 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
121a3581
RR
772 m_frameMenuBar->m_x = xx;
773 m_frameMenuBar->m_y = yy;
774 m_frameMenuBar->m_width = ww;
775 m_frameMenuBar->m_height = hh;
da048e3d 776 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 777 m_frameMenuBar->m_widget,
f03fc89f
VZ
778 xx, yy, ww, hh );
779 client_area_y_offset += hh;
ab2b3dd4 780 }
88ac883a 781
dcf924a3 782#if wxUSE_TOOLBAR
11e1c70d 783 if ((m_frameToolBar) &&
7beba2fc 784 (m_frameToolBar->m_widget->parent == m_mainWidget))
ab2b3dd4
RR
785 {
786 int xx = m_miniEdge;
787 int yy = m_miniEdge + m_miniTitle;
41ca191f 788 if (m_frameMenuBar)
f03fc89f 789 {
88ac883a
VZ
790 if (!m_menuBarDetached)
791 yy += wxMENU_HEIGHT;
792 else
f03fc89f
VZ
793 yy += wxPLACE_HOLDER;
794 }
93fa69f8 795
121a3581
RR
796 m_frameToolBar->m_x = xx;
797 m_frameToolBar->m_y = yy;
93fa69f8
VZ
798
799 /* don't change the toolbar's reported height/width */
800 int ww, hh;
801 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
802 {
803 ww = m_toolBarDetached ? wxPLACE_HOLDER
804 : m_frameToolBar->m_width;
805 hh = m_height - 2*m_miniEdge;
806
807 client_area_x_offset += ww;
808 }
809 else
810 {
811 ww = m_width - 2*m_miniEdge;
812 hh = m_toolBarDetached ? wxPLACE_HOLDER
813 : m_frameToolBar->m_height;
814
815 client_area_y_offset += hh;
816 }
817
da048e3d 818 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 819 m_frameToolBar->m_widget,
f03fc89f 820 xx, yy, ww, hh );
ab2b3dd4 821 }
93fa69f8 822#endif // wxUSE_TOOLBAR
88ac883a 823
93fa69f8 824 int client_x = client_area_x_offset + m_miniEdge;
f03fc89f 825 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
93fa69f8 826 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
f03fc89f 827 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
da048e3d 828 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 829 m_wxwindow,
f03fc89f 830 client_x, client_y, client_w, client_h );
32a95f9f
RR
831 }
832 else
833 {
834 /* if there is no m_mainWidget between m_widget and m_wxwindow there
f03fc89f 835 is no need to set the size or position of m_wxwindow. */
f5368809 836 }
88ac883a 837
dcf924a3 838#if wxUSE_STATUSBAR
f5368809
RR
839 if (m_frameStatusBar)
840 {
b2b3ccc5 841 int xx = 0 + m_miniEdge;
f362b96d 842 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
ac57418f
RR
843 int ww = m_width - 2*m_miniEdge;
844 int hh = wxSTATUS_HEIGHT;
121a3581
RR
845 m_frameStatusBar->m_x = xx;
846 m_frameStatusBar->m_y = yy;
847 m_frameStatusBar->m_width = ww;
848 m_frameStatusBar->m_height = hh;
da048e3d 849 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
7c0ea335
VZ
850 m_frameStatusBar->m_widget,
851 xx, yy, ww, hh );
b6fa52db 852 gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
f5368809 853 }
dcf924a3 854#endif
8bbe427f 855
54517652 856 m_sizeSet = TRUE;
7beba2fc 857
54517652 858 // send size event to frame
43a18898
RR
859 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
860 event.SetEventObject( this );
e52f60e6 861 GetEventHandler()->ProcessEvent( event );
8bbe427f 862
54517652 863 // send size event to status bar
5aa5e35a
RR
864 if (m_frameStatusBar)
865 {
a2053b27 866 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
5aa5e35a
RR
867 event2.SetEventObject( m_frameStatusBar );
868 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
869 }
884470b1 870
e52f60e6
RR
871 m_resizing = FALSE;
872}
873
ca26177c
RR
874void wxFrame::MakeModal( bool modal )
875{
876 if (modal)
ca26177c 877 gtk_grab_add( m_widget );
ca26177c 878 else
c25ccf85 879 gtk_grab_remove( m_widget );
ca26177c
RR
880}
881
9390a202 882void wxFrame::OnInternalIdle()
e52f60e6 883{
1b3667ab 884 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
54517652 885 {
e52f60e6 886 GtkOnSize( m_x, m_y, m_width, m_height );
7beba2fc
VZ
887
888 // we'll come back later
54517652
RR
889 if (g_isIdle)
890 wxapp_install_idle_handler();
7beba2fc 891 return;
54517652 892 }
88ac883a 893
082b2798 894 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
dcf924a3 895#if wxUSE_TOOLBAR
082b2798 896 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
dcf924a3
RR
897#endif
898#if wxUSE_STATUSBAR
082b2798 899 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
dcf924a3 900#endif
5e014a0c
RR
901
902 wxWindow::OnInternalIdle();
362c6693 903}
c801d85f 904
7c0ea335
VZ
905// ----------------------------------------------------------------------------
906// menu/tool/status bar stuff
907// ----------------------------------------------------------------------------
c801d85f 908
c801d85f
KB
909void wxFrame::SetMenuBar( wxMenuBar *menuBar )
910{
223d09f6
KB
911 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
912 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
8bbe427f 913
186baeb2
RR
914 if (menuBar == m_frameMenuBar)
915 return;
916
917 if (m_frameMenuBar)
918 {
919 m_frameMenuBar->UnsetInvokingWindow( this );
920
921 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
922 {
923 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
924 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
925
926 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
927 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
928 }
929
930 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
931 gtk_widget_ref( m_frameMenuBar->m_widget );
932 gtk_widget_unparent( m_frameMenuBar->m_widget );
933 }
934
f5368809 935 m_frameMenuBar = menuBar;
8bbe427f 936
f5368809 937 if (m_frameMenuBar)
30dea054 938 {
5bd9e519 939 m_frameMenuBar->SetInvokingWindow( this );
8bbe427f 940
186baeb2
RR
941 m_frameMenuBar->SetParent(this);
942 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
88ac883a
VZ
943 m_frameMenuBar->m_widget,
944 m_frameMenuBar->m_x,
a2053b27
RR
945 m_frameMenuBar->m_y,
946 m_frameMenuBar->m_width,
947 m_frameMenuBar->m_height );
88ac883a 948
186baeb2
RR
949 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
950 {
951 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
952 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
7beba2fc 953
186baeb2
RR
954 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
955 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
f5368809 956 }
186baeb2
RR
957
958 m_frameMenuBar->Show( TRUE );
716b7364 959 }
8bbe427f 960
1e133b7d 961 /* resize window in OnInternalIdle */
5b077d48 962 m_sizeSet = FALSE;
362c6693 963}
c801d85f 964
88ac883a 965#if wxUSE_TOOLBAR
6bc8a1c8 966wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
46dc76ba 967{
223d09f6 968 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 969
6bc8a1c8 970 m_insertInClientArea = FALSE;
88ac883a 971
7c0ea335 972 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
8bbe427f 973
7c0ea335
VZ
974 if (m_frameToolBar)
975 GetChildren().DeleteObject( m_frameToolBar );
88ac883a 976
6bc8a1c8 977 m_insertInClientArea = TRUE;
8bbe427f 978
5b077d48 979 m_sizeSet = FALSE;
8bbe427f 980
f5368809 981 return m_frameToolBar;
362c6693 982}
46dc76ba 983
7beba2fc
VZ
984void wxFrame::SetToolBar(wxToolBar *toolbar)
985{
7c0ea335
VZ
986 wxFrameBase::SetToolBar(toolbar);
987
307f16e8
RR
988 if (m_frameToolBar)
989 {
990 /* insert into toolbar area if not already there */
3017f78d
RR
991 if ((m_frameToolBar->m_widget->parent) &&
992 (m_frameToolBar->m_widget->parent != m_mainWidget))
307f16e8 993 {
3017f78d 994 GetChildren().DeleteObject( m_frameToolBar );
7beba2fc
VZ
995
996 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
5b8a521e 997 GtkUpdateSize();
7beba2fc 998 }
307f16e8
RR
999 }
1000}
1001
88ac883a 1002#endif // wxUSE_TOOLBAR
46dc76ba 1003
88ac883a 1004#if wxUSE_STATUSBAR
8bbe427f 1005
7c0ea335
VZ
1006wxStatusBar* wxFrame::CreateStatusBar(int number,
1007 long style,
1008 wxWindowID id,
1009 const wxString& name)
c801d85f 1010{
223d09f6 1011 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1012
7c0ea335
VZ
1013 // because it will change when toolbar is added
1014 m_sizeSet = FALSE;
c801d85f 1015
7c0ea335 1016 return wxFrameBase::CreateStatusBar( number, style, id, name );
362c6693
RR
1017}
1018
8febdd39
RR
1019void wxFrame::PositionStatusBar()
1020{
1021 if ( !m_frameStatusBar )
1022 return;
1023
1024 m_sizeSet = FALSE;
1025}
88ac883a 1026#endif // wxUSE_STATUSBAR
c801d85f 1027
7c0ea335
VZ
1028// ----------------------------------------------------------------------------
1029// frame title/icon
1030// ----------------------------------------------------------------------------
c801d85f 1031
c801d85f
KB
1032void wxFrame::SetTitle( const wxString &title )
1033{
223d09f6 1034 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1035
f5368809 1036 m_title = title;
ed9b9841 1037 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
362c6693 1038}
c801d85f 1039
d355d3fe
RR
1040void wxFrame::SetIcon( const wxIcon &icon )
1041{
223d09f6 1042 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1043
7c0ea335 1044 wxFrameBase::SetIcon(icon);
8bbe427f 1045
7c0ea335
VZ
1046 if ( !m_icon.Ok() )
1047 return;
1048
1049 if (!m_widget->window)
1050 return;
58dea4b0 1051
f5368809
RR
1052 wxMask *mask = icon.GetMask();
1053 GdkBitmap *bm = (GdkBitmap *) NULL;
1054 if (mask) bm = mask->GetBitmap();
8bbe427f 1055
f5368809 1056 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
d355d3fe 1057}
b2b3ccc5 1058
7c0ea335
VZ
1059// ----------------------------------------------------------------------------
1060// frame state: maximized/iconized/normal (TODO)
1061// ----------------------------------------------------------------------------
1062
7beba2fc 1063void wxFrame::Maximize(bool WXUNUSED(maximize))
cd25b18c
RR
1064{
1065}
1066
7c0ea335
VZ
1067bool wxFrame::IsMaximized() const
1068{
1069 return FALSE;
1070}
1071
7beba2fc 1072void wxFrame::Restore()
cd25b18c
RR
1073{
1074}
1075
7beba2fc
VZ
1076void wxFrame::Iconize( bool iconize )
1077{
cd25b18c
RR
1078 if (iconize)
1079 {
1080 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
7beba2fc
VZ
1081 GDK_WINDOW_XWINDOW( m_widget->window ),
1082 DefaultScreen( GDK_DISPLAY() ) );
cd25b18c
RR
1083 }
1084}
1085
7beba2fc
VZ
1086bool wxFrame::IsIconized() const
1087{
1088 return FALSE;
cd25b18c 1089}