]> git.saurik.com Git - wxWidgets.git/blame - src/motif/frame.cpp
1. some fixes for the problems reported by BoundsChecker
[wxWidgets.git] / src / motif / frame.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
1c4f8f8d 2// Name: motif/frame.cpp
4bb6408c
JS
3// Purpose: wxFrame
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
1c4f8f8d
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
4bb6408c 20#ifdef __GNUG__
1c4f8f8d 21 #pragma implementation "frame.h"
4bb6408c
JS
22#endif
23
24#include "wx/frame.h"
25#include "wx/statusbr.h"
26#include "wx/toolbar.h"
27#include "wx/menuitem.h"
28#include "wx/menu.h"
29#include "wx/dcclient.h"
30#include "wx/dialog.h"
31#include "wx/settings.h"
32#include "wx/app.h"
33#include "wx/utils.h"
176513eb 34#include "wx/log.h"
4bb6408c 35
338dd992 36#ifdef __VMS__
1c4f8f8d 37 #pragma message disable nosimpint
338dd992 38#endif
1c4f8f8d 39
4bb6408c 40#if defined(__ultrix) || defined(__sgi)
1c4f8f8d 41 #include <Xm/Frame.h>
4bb6408c
JS
42#endif
43
44#include <Xm/Xm.h>
45#include <X11/Shell.h>
46#if XmVersion >= 1002
1c4f8f8d 47 #include <Xm/XmAll.h>
4bb6408c 48#else
1c4f8f8d 49 #include <Xm/Frame.h>
4bb6408c
JS
50#endif
51#include <Xm/MwmUtil.h>
52#include <Xm/BulletinB.h>
53#include <Xm/Form.h>
54#include <Xm/MainW.h>
55#include <Xm/RowColumn.h>
56#include <Xm/Label.h>
57#include <Xm/AtomMgr.h>
58#include <Xm/LabelG.h>
59#include <Xm/Frame.h>
60#if XmVersion > 1000
1c4f8f8d 61 #include <Xm/Protocols.h>
4bb6408c 62#endif
1c4f8f8d 63
338dd992 64#ifdef __VMS__
1c4f8f8d 65 #pragma message enable nosimpint
338dd992 66#endif
4bb6408c
JS
67
68#include "wx/motif/private.h"
69
1c4f8f8d
VZ
70// ----------------------------------------------------------------------------
71// private functions
72// ----------------------------------------------------------------------------
73
74static void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs);
75static void wxFrameFocusProc(Widget workArea, XtPointer clientData,
76 XmAnyCallbackStruct *cbs);
dfe1eee3 77static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
2d120f83 78 XCrossingEvent * event);
4bb6408c 79
1c4f8f8d
VZ
80// ----------------------------------------------------------------------------
81// globals
82// ----------------------------------------------------------------------------
83
4bb6408c
JS
84extern wxList wxModelessWindows;
85extern wxList wxPendingDelete;
86
87// TODO: this should be tidied so that any frame can be the
88// top frame
89static bool wxTopLevelUsed = FALSE;
90
1c4f8f8d
VZ
91// ----------------------------------------------------------------------------
92// wxWin macros
93// ----------------------------------------------------------------------------
94
1c4f8f8d
VZ
95BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
96 EVT_ACTIVATE(wxFrame::OnActivate)
97 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
4bb6408c
JS
98END_EVENT_TABLE()
99
c0854a08 100IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
4bb6408c 101
1c4f8f8d
VZ
102// ============================================================================
103// implementation
104// ============================================================================
1ccbb61a 105
1c4f8f8d
VZ
106// ----------------------------------------------------------------------------
107// frame construction
108// ----------------------------------------------------------------------------
dfe1eee3 109
1c4f8f8d
VZ
110void wxFrame::Init()
111{
4bb6408c 112 m_iconized = FALSE;
dfe1eee3 113
4bb6408c
JS
114 //// Motif-specific
115 m_frameShell = (WXWidget) NULL;
116 m_frameWidget = (WXWidget) NULL;;
117 m_workArea = (WXWidget) NULL;;
118 m_clientArea = (WXWidget) NULL;;
119 m_visibleStatus = TRUE;
4bb6408c
JS
120}
121
122bool wxFrame::Create(wxWindow *parent,
2d120f83
JS
123 wxWindowID id,
124 const wxString& title,
125 const wxPoint& pos,
126 const wxSize& size,
127 long style,
128 const wxString& name)
4bb6408c 129{
1c4f8f8d
VZ
130 if ( parent )
131 AddChild(this);
132 else
2d120f83 133 wxTopLevelWindows.Append(this);
dfe1eee3 134
1c4f8f8d
VZ
135 wxModelessWindows.Append(this);
136
2d120f83 137 SetName(name);
dfe1eee3 138
2d120f83 139 m_windowStyle = style;
dfe1eee3 140
2d120f83
JS
141 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE);
142 m_foregroundColour = *wxBLACK;
da175b2c 143 m_font = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
dfe1eee3 144
2d120f83
JS
145 if ( id > -1 )
146 m_windowId = id;
147 else
148 m_windowId = (int)NewControlId();
dfe1eee3 149
447a039f
MB
150 int x = pos.x, y = pos.y;
151 int width = size.x, height = size.y;
da8bed9b
VZ
152
153 // Set reasonable values for position and size if defaults have been
154 // requested
447a039f 155 //
da8bed9b
VZ
156 // MB TODO: something better than these arbitrary values ?
157 // VZ should use X resources for this...
158 if ( width == -1 )
159 width = 400;
160 if ( height == -1 )
161 height = 400;
447a039f
MB
162
163 int displayW, displayH;
164 wxDisplaySize( &displayW, &displayH );
165
166 if ( x == -1 )
167 {
168 x = (displayW - width) / 2;
169 if (x < 10) x = 10;
170 }
171 if ( y == -1 )
172 {
173 y = (displayH - height) / 2;
da8bed9b 174 if (y < 10) y = 10;
447a039f 175 }
da8bed9b 176
1c4f8f8d 177 // VZ: what does this do??
2d120f83 178 if (wxTopLevelUsed)
31528cd3 179 {
2d120f83 180 // Change suggested by Matthew Flatt
31528cd3
VZ
181 m_frameShell = (WXWidget)XtAppCreateShell
182 (
183 name,
184 wxTheApp->GetClassName(),
185 topLevelShellWidgetClass,
186 (Display*) wxGetDisplay(),
187 NULL,
188 0
189 );
190 }
2d120f83
JS
191 else
192 {
193 m_frameShell = wxTheApp->GetTopLevelWidget();
194 wxTopLevelUsed = TRUE;
195 }
dfe1eee3
VZ
196
197 XtVaSetValues((Widget) m_frameShell,
2d120f83
JS
198 // Allows menu to resize
199 XmNallowShellResize, True,
200 XmNdeleteResponse, XmDO_NOTHING,
201 XmNmappedWhenManaged, False,
202 XmNiconic, (style & wxICONIZE) ? TRUE : FALSE,
203 NULL);
dfe1eee3 204
1c4f8f8d 205 if (!title.IsEmpty())
dfe1eee3 206 XtVaSetValues((Widget) m_frameShell,
1c4f8f8d 207 XmNtitle, title.c_str(),
2d120f83 208 NULL);
dfe1eee3 209
2d120f83
JS
210 m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window",
211 xmMainWindowWidgetClass, (Widget) m_frameShell,
212 XmNresizePolicy, XmRESIZE_NONE,
213 NULL);
dfe1eee3 214
2d120f83
JS
215 m_workArea = (WXWidget) XtVaCreateWidget("form",
216 xmFormWidgetClass, (Widget) m_frameWidget,
217 XmNresizePolicy, XmRESIZE_NONE,
218 NULL);
dfe1eee3 219
2d120f83
JS
220 m_clientArea = (WXWidget) XtVaCreateWidget("client",
221 xmBulletinBoardWidgetClass, (Widget) m_workArea,
222 XmNmarginWidth, 0,
223 XmNmarginHeight, 0,
224 XmNrightAttachment, XmATTACH_FORM,
225 XmNleftAttachment, XmATTACH_FORM,
226 XmNtopAttachment, XmATTACH_FORM,
227 XmNbottomAttachment, XmATTACH_FORM,
228 // XmNresizePolicy, XmRESIZE_ANY,
229 NULL);
0492c5a0 230
1c4f8f8d
VZ
231 wxLogTrace(wxTRACE_Messages,
232 "Created frame (0x%08x) with work area 0x%08x and client "
31528cd3
VZ
233 "area 0x%08x", m_frameWidget, m_workArea, m_clientArea);
234
2e35f56f
JS
235 XtAddEventHandler((Widget) m_clientArea, ExposureMask,FALSE,
236 wxUniversalRepaintProc, (XtPointer) this);
dfe1eee3 237
2d120f83
JS
238 XtVaSetValues((Widget) m_frameWidget,
239 XmNworkWindow, (Widget) m_workArea,
240 NULL);
dfe1eee3 241
2d120f83
JS
242 XtManageChild((Widget) m_clientArea);
243 XtManageChild((Widget) m_workArea);
dfe1eee3 244
2d120f83 245 wxAddWindowToTable((Widget) m_workArea, this);
dfe1eee3 246
1c4f8f8d 247 XtTranslations ptr;
dfe1eee3 248
2d120f83
JS
249 XtOverrideTranslations((Widget) m_workArea,
250 ptr = XtParseTranslationTable("<Configure>: resize()"));
dfe1eee3 251
2d120f83 252 XtFree((char *)ptr);
dfe1eee3
VZ
253
254 XtAddCallback((Widget) m_workArea, XmNfocusCallback,
2d120f83 255 (XtCallbackProc)wxFrameFocusProc, (XtPointer)this);
dfe1eee3 256
2d120f83
JS
257 /* Part of show-&-hide fix */
258 XtAddEventHandler((Widget) m_frameShell, StructureNotifyMask,
259 False, (XtEventHandler)wxFrameMapProc,
260 (XtPointer)m_workArea);
dfe1eee3 261
2d120f83
JS
262 if (x > -1)
263 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
264 if (y > -1)
265 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
266 if (width > -1)
267 XtVaSetValues((Widget) m_frameShell, XmNwidth, width, NULL);
268 if (height > -1)
269 XtVaSetValues((Widget) m_frameShell, XmNheight, height, NULL);
dfe1eee3 270
2d120f83 271 m_mainWidget = m_frameWidget;
dfe1eee3 272
2d120f83 273 ChangeFont(FALSE);
dfe1eee3 274
2d120f83
JS
275 // This patch comes from Torsten Liermann lier@lier1.muc.de
276 if (XmIsMotifWMRunning( (Widget) m_frameShell ))
277 {
1c4f8f8d 278 int decor = 0;
2d120f83 279 if (style & wxRESIZE_BORDER)
1c4f8f8d 280 decor |= MWM_DECOR_RESIZEH;
2d120f83
JS
281 if (style & wxSYSTEM_MENU)
282 decor |= MWM_DECOR_MENU;
283 if ((style & wxCAPTION) ||
284 (style & wxTINY_CAPTION_HORIZ) ||
285 (style & wxTINY_CAPTION_VERT))
286 decor |= MWM_DECOR_TITLE;
287 if (style & wxTHICK_FRAME)
288 decor |= MWM_DECOR_BORDER;
289 if (style & wxTHICK_FRAME)
290 decor |= MWM_DECOR_BORDER;
291 if (style & wxMINIMIZE_BOX)
292 decor |= MWM_DECOR_MINIMIZE;
293 if (style & wxMAXIMIZE_BOX)
294 decor |= MWM_DECOR_MAXIMIZE;
1c4f8f8d 295 XtVaSetValues((Widget) m_frameShell,XmNmwmDecorations,decor,NULL);
2d120f83
JS
296 }
297 // This allows non-Motif window managers to support at least the
298 // no-decorations case.
299 else
300 {
301 if (style == 0)
302 XtVaSetValues((Widget) m_frameShell,XmNoverrideRedirect,TRUE,NULL);
303 }
304 XtRealizeWidget((Widget) m_frameShell);
dfe1eee3 305
2d120f83
JS
306 // Intercept CLOSE messages from the window manager
307 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay((Widget) m_frameShell), "WM_DELETE_WINDOW", False);
4bb6408c 308#if (XmREVISION > 1 || XmVERSION > 1)
2d120f83 309 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (XtPointer)this);
4bb6408c
JS
310#else
311#if XmREVISION == 1
2d120f83 312 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (caddr_t)this);
4bb6408c 313#else
2d120f83 314 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this);
4bb6408c
JS
315#endif
316#endif
dfe1eee3 317
2d120f83 318 ChangeBackgroundColour();
dfe1eee3 319
2d120f83 320 PreResize();
dfe1eee3 321
2d120f83
JS
322 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
323 sizeEvent.SetEventObject(this);
dfe1eee3 324
2d120f83 325 GetEventHandler()->ProcessEvent(sizeEvent);
dfe1eee3 326
2d120f83 327 return TRUE;
4bb6408c
JS
328}
329
330wxFrame::~wxFrame()
331{
3ab377bd 332 m_isBeingDeleted = TRUE;
da8bed9b 333
2e35f56f
JS
334 if (m_clientArea)
335 XtRemoveEventHandler((Widget) m_clientArea, ExposureMask, FALSE,
336 wxUniversalRepaintProc, (XtPointer) this);
337
2d120f83
JS
338 if (GetMainWidget())
339 Show(FALSE);
0492c5a0 340
2d120f83
JS
341 if (m_frameMenuBar)
342 {
343 m_frameMenuBar->DestroyMenuBar();
dfe1eee3 344
2d120f83 345 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
4bb6408c 346#if MOTIF_MENUBAR_DELETE_FIX
2d120f83 347 GetMenuBar()->SetMainWidget((WXWidget) NULL);
4bb6408c 348#endif
2d120f83
JS
349 delete m_frameMenuBar;
350 m_frameMenuBar = NULL;
351 }
dfe1eee3 352
2d120f83
JS
353 wxTopLevelWindows.DeleteObject(this);
354 wxModelessWindows.DeleteObject(this);
dfe1eee3 355
2d120f83 356 if (m_frameStatusBar)
1c4f8f8d 357 {
2d120f83 358 delete m_frameStatusBar;
1c4f8f8d
VZ
359 m_frameStatusBar = NULL;
360 }
dfe1eee3 361
2d120f83 362 DestroyChildren();
dfe1eee3 363
2d120f83 364 if (m_workArea)
4bb6408c 365 {
2d120f83 366 wxDeleteWindowFromTable((Widget) m_workArea);
dfe1eee3 367
2d120f83 368 XtDestroyWidget ((Widget) m_workArea);
4bb6408c 369 }
dfe1eee3 370
2d120f83
JS
371 if (m_frameWidget)
372 {
373 wxDeleteWindowFromTable((Widget) m_frameWidget);
374 XtDestroyWidget ((Widget) m_frameWidget);
375 }
dfe1eee3 376
2d120f83
JS
377 if (m_frameShell)
378 XtDestroyWidget ((Widget) m_frameShell);
dfe1eee3 379
2d120f83 380 SetMainWidget((WXWidget) NULL);
dfe1eee3 381
2d120f83 382 /* Check if it's the last top-level window */
dfe1eee3 383
2d120f83
JS
384 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
385 {
386 wxTheApp->SetTopWindow(NULL);
dfe1eee3 387
2d120f83
JS
388 if (wxTheApp->GetExitOnFrameDelete())
389 {
390 // Signal to the app that we're going to close
391 wxTheApp->ExitMainLoop();
392 }
393 }
4bb6408c
JS
394}
395
396// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
449f38b5 397void wxFrame::DoGetClientSize(int *x, int *y) const
4bb6408c 398{
2d120f83
JS
399 Dimension xx, yy;
400 XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL);
dfe1eee3 401
2d120f83
JS
402 if (m_frameStatusBar)
403 {
404 int sbw, sbh;
405 m_frameStatusBar->GetSize(& sbw, & sbh);
406 yy -= sbh;
407 }
1ccbb61a 408#if wxUSE_TOOLBAR
2d120f83
JS
409 if (m_frameToolBar)
410 {
411 int tbw, tbh;
412 m_frameToolBar->GetSize(& tbw, & tbh);
413 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
414 xx -= tbw;
415 else
416 yy -= tbh;
417 }
1ccbb61a 418#endif // wxUSE_TOOLBAR
2d120f83
JS
419 /*
420 if (GetMenuBar() != (wxMenuBar*) NULL)
421 {
4bb6408c
JS
422 // it seems that if a frame holds a panel, the menu bar size
423 // gets automatically taken care of --- grano@cs.helsinki.fi 4.4.95
424 bool hasSubPanel = FALSE;
c0ed460c 425 for(wxNode* node = GetChildren().First(); node; node = node->Next())
4bb6408c 426 {
2d120f83
JS
427 wxWindow *win = (wxWindow *)node->Data();
428 hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog)));
dfe1eee3 429
4bb6408c 430 if (hasSubPanel)
2d120f83
JS
431 break;
432 }
433 if (! hasSubPanel) {
4bb6408c
JS
434 Dimension ys;
435 XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL);
436 yy -= ys;
2d120f83
JS
437 }
438 }
439 */
dfe1eee3 440
2d120f83 441 *x = xx; *y = yy;
4bb6408c
JS
442}
443
444// Set the client size (i.e. leave the calculation of borders etc.
445// to wxWindows)
bfc6fde4 446void wxFrame::DoSetClientSize(int width, int height)
4bb6408c 447{
2d120f83
JS
448 // Calculate how large the new main window should be
449 // by finding the difference between the client area and the
450 // main window area, and adding on to the new client area
451 if (width > -1)
452 XtVaSetValues((Widget) m_workArea, XmNwidth, width, NULL);
dfe1eee3 453
2d120f83 454 if (height > -1)
a4294b78 455 {
2d120f83
JS
456 if (m_frameStatusBar)
457 {
458 int sbw, sbh;
459 m_frameStatusBar->GetSize(& sbw, & sbh);
460 height += sbh;
461 }
1ccbb61a 462#if wxUSE_TOOLBAR
2d120f83
JS
463 if (m_frameToolBar)
464 {
465 int tbw, tbh;
466 m_frameToolBar->GetSize(& tbw, & tbh);
467 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
468 width += tbw;
469 else
470 height += tbh;
471 }
1ccbb61a 472#endif // wxUSE_TOOLBAR
dfe1eee3 473
2d120f83 474 XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL);
a4294b78 475 }
2d120f83 476 PreResize();
dfe1eee3 477
2d120f83
JS
478 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
479 sizeEvent.SetEventObject(this);
dfe1eee3 480
2d120f83 481 GetEventHandler()->ProcessEvent(sizeEvent);
dfe1eee3 482
4bb6408c
JS
483}
484
449f38b5 485void wxFrame::DoGetSize(int *width, int *height) const
4bb6408c 486{
2d120f83
JS
487 Dimension xx, yy;
488 XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL);
489 *width = xx; *height = yy;
4bb6408c
JS
490}
491
449f38b5 492void wxFrame::DoGetPosition(int *x, int *y) const
4bb6408c
JS
493{
494 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
495 next_parent = XtWindow((Widget) m_frameShell),
496 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
dfe1eee3 497
4bb6408c
JS
498 // search for the parent that is child of ROOT, because the WM may
499 // reparent twice and notify only the next parent (like FVWM)
500 while (next_parent != root) {
2d120f83
JS
501 Window *theChildren; unsigned int n;
502 parent_window = next_parent;
503 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
504 &next_parent, &theChildren, &n);
505 XFree(theChildren); // not needed
4bb6408c
JS
506 }
507 int xx, yy; unsigned int dummy;
508 XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root,
2d120f83 509 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
4bb6408c
JS
510 if (x) *x = xx;
511 if (y) *y = yy;
512}
513
af111fc3 514void wxFrame::DoSetSize(int x, int y, int width, int height, int WXUNUSED(sizeFlags))
4bb6408c 515{
2d120f83
JS
516 if (x > -1)
517 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
518 if (y > -1)
519 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
520 if (width > -1)
521 XtVaSetValues((Widget) m_frameWidget, XmNwidth, width, NULL);
522 if (height > -1)
523 XtVaSetValues((Widget) m_frameWidget, XmNheight, height, NULL);
dfe1eee3 524
2d120f83
JS
525 if (!(height == -1 && width == -1))
526 {
527 PreResize();
dfe1eee3 528
2d120f83
JS
529 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
530 sizeEvent.SetEventObject(this);
dfe1eee3 531
2d120f83
JS
532 GetEventHandler()->ProcessEvent(sizeEvent);
533 }
4bb6408c
JS
534}
535
536bool wxFrame::Show(bool show)
537{
2d120f83
JS
538 if (!m_frameShell)
539 return wxWindow::Show(show);
dfe1eee3 540
2d120f83 541 m_visibleStatus = show; /* show-&-hide fix */
dfe1eee3 542
2d120f83
JS
543 m_isShown = show;
544 if (show) {
545 XtMapWidget((Widget) m_frameShell);
546 XRaiseWindow(XtDisplay((Widget) m_frameShell), XtWindow((Widget) m_frameShell));
547 } else {
548 XtUnmapWidget((Widget) m_frameShell);
549 // XmUpdateDisplay(wxTheApp->topLevel); // Experimental: may be responsible for crashes
550 }
551 return TRUE;
4bb6408c
JS
552}
553
554void wxFrame::Iconize(bool iconize)
555{
2d120f83
JS
556 if (!iconize)
557 Show(TRUE);
dfe1eee3 558
2d120f83
JS
559 if (m_frameShell)
560 XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL);
4bb6408c
JS
561}
562
1c4f8f8d
VZ
563void wxFrame::Restore()
564{
565 if ( m_frameShell )
566 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
567}
568
4bb6408c
JS
569void wxFrame::Maximize(bool maximize)
570{
2d120f83 571 Show(TRUE);
dfe1eee3 572
1c4f8f8d
VZ
573 if ( maximize )
574 Restore();
4bb6408c
JS
575}
576
577bool wxFrame::IsIconized() const
578{
2d120f83
JS
579 if (!m_frameShell)
580 return FALSE;
dfe1eee3 581
2d120f83
JS
582 Boolean iconic;
583 XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL);
584 return iconic;
4bb6408c
JS
585}
586
6f63ec3f 587// Is it maximized?
1c4f8f8d 588bool wxFrame::IsMaximized() const
6f63ec3f
JS
589{
590 // No maximizing in Motif (?)
591 return FALSE;
592}
593
4bb6408c
JS
594void wxFrame::SetTitle(const wxString& title)
595{
2d120f83
JS
596 if (title == m_title)
597 return;
dfe1eee3 598
2d120f83 599 m_title = title;
dfe1eee3 600
2d120f83 601 if (!title.IsNull())
dfe1eee3 602 XtVaSetValues((Widget) m_frameShell,
1c4f8f8d
VZ
603 XmNtitle, title.c_str(),
604 XmNiconName, title.c_str(),
2d120f83 605 NULL);
4bb6408c
JS
606}
607
608void wxFrame::SetIcon(const wxIcon& icon)
609{
2d120f83 610 m_icon = icon;
dfe1eee3 611
2d120f83
JS
612 if (!m_frameShell)
613 return;
dfe1eee3 614
2d120f83
JS
615 if (!icon.Ok() || !icon.GetPixmap())
616 return;
dfe1eee3 617
2d120f83 618 XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL);
4bb6408c
JS
619}
620
4bb6408c
JS
621void wxFrame::PositionStatusBar()
622{
50414e24 623 if (!m_frameStatusBar)
2d120f83 624 return;
dfe1eee3 625
4bb6408c
JS
626 int w, h;
627 GetClientSize(&w, &h);
628 int sw, sh;
629 m_frameStatusBar->GetSize(&sw, &sh);
dfe1eee3 630
4bb6408c
JS
631 // Since we wish the status bar to be directly under the client area,
632 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
89c7e962 633 m_frameStatusBar->SetSize(0, h, w, sh);
4bb6408c
JS
634}
635
636WXWidget wxFrame::GetMenuBarWidget() const
637{
2d120f83
JS
638 if (GetMenuBar())
639 return GetMenuBar()->GetMainWidget();
640 else
641 return (WXWidget) NULL;
4bb6408c
JS
642}
643
644void wxFrame::SetMenuBar(wxMenuBar *menuBar)
645{
646 if (!menuBar)
647 {
648 m_frameMenuBar = NULL;
649 return;
650 }
dfe1eee3 651
4bb6408c 652 // Currently can't set it twice
2d120f83 653 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
dfe1eee3 654
621793f4 655 if (m_frameMenuBar)
4bb6408c 656 {
621793f4
JS
657 m_frameMenuBar->DestroyMenuBar();
658 delete m_frameMenuBar;
4bb6408c 659 }
dfe1eee3 660
621793f4
JS
661 m_frameMenuBar = menuBar;
662 m_frameMenuBar->CreateMenuBar(this);
4bb6408c
JS
663}
664
4bb6408c
JS
665// Responds to colour changes, and passes event on to children.
666void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
667{
668 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
669 Refresh();
dfe1eee3 670
4bb6408c
JS
671 if ( m_frameStatusBar )
672 {
673 wxSysColourChangedEvent event2;
674 event2.SetEventObject( m_frameStatusBar );
675 m_frameStatusBar->ProcessEvent(event2);
676 }
dfe1eee3 677
4bb6408c
JS
678 // Propagate the event to the non-top-level children
679 wxWindow::OnSysColourChanged(event);
680}
681
4bb6408c
JS
682// Default activation behaviour - set the focus for the first child
683// subwindow found.
684void wxFrame::OnActivate(wxActivateEvent& event)
685{
af111fc3
JS
686 if (!event.GetActive())
687 return;
688
2d120f83 689 for(wxNode *node = GetChildren().First(); node; node = node->Next())
4bb6408c 690 {
2d120f83
JS
691 // Find a child that's a subwindow, but not a dialog box.
692 wxWindow *child = (wxWindow *)node->Data();
693 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
694 !child->IsKindOf(CLASSINFO(wxDialog)))
695 {
696 child->SetFocus();
697 return;
698 }
4bb6408c 699 }
4bb6408c
JS
700}
701
1ccbb61a 702#if wxUSE_TOOLBAR
dfe1eee3 703
1c4f8f8d
VZ
704wxToolBar* wxFrame::CreateToolBar(long style,
705 wxWindowID id,
706 const wxString& name)
4bb6408c 707{
1c4f8f8d 708 if ( wxFrameBase::CreateToolBar(style, id, name) )
4bb6408c 709 {
4bb6408c 710 PositionToolBar();
4bb6408c 711 }
4bb6408c 712
1ccbb61a
VZ
713 return m_frameToolBar;
714}
715
4bb6408c
JS
716void wxFrame::PositionToolBar()
717{
4bb6408c
JS
718 if (GetToolBar())
719 {
1c4f8f8d
VZ
720 int cw, ch;
721 GetClientSize(& cw, &ch);
722
4bb6408c
JS
723 int tw, th;
724 GetToolBar()->GetSize(& tw, & th);
dfe1eee3 725
4bb6408c
JS
726 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
727 {
728 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
729 // means, pretend we don't have toolbar/status bar, so we
730 // have the original client size.
a4294b78 731 GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS);
4bb6408c
JS
732 }
733 else
734 {
735 // Use the 'real' position
736 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
737 }
738 }
739}
1ccbb61a 740#endif // wxUSE_TOOLBAR
4bb6408c 741
1c4f8f8d 742void wxFrame::Raise()
4bb6408c
JS
743{
744 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
745 next_parent = XtWindow((Widget) m_frameShell),
746 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
4bb6408c
JS
747 // search for the parent that is child of ROOT, because the WM may
748 // reparent twice and notify only the next parent (like FVWM)
749 while (next_parent != root) {
2d120f83
JS
750 Window *theChildren; unsigned int n;
751 parent_window = next_parent;
752 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
753 &next_parent, &theChildren, &n);
754 XFree(theChildren); // not needed
4bb6408c
JS
755 }
756 XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window);
757}
758
1c4f8f8d 759void wxFrame::Lower()
4bb6408c
JS
760{
761 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
762 next_parent = XtWindow((Widget) m_frameShell),
763 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
4bb6408c
JS
764 // search for the parent that is child of ROOT, because the WM may
765 // reparent twice and notify only the next parent (like FVWM)
766 while (next_parent != root) {
2d120f83
JS
767 Window *theChildren; unsigned int n;
768 parent_window = next_parent;
769 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
770 &next_parent, &theChildren, &n);
771 XFree(theChildren); // not needed
4bb6408c
JS
772 }
773 XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window);
774}
775
af111fc3
JS
776void wxFrameFocusProc(Widget WXUNUSED(workArea), XtPointer WXUNUSED(clientData),
777 XmAnyCallbackStruct *WXUNUSED(cbs))
4bb6408c 778{
2d120f83
JS
779 // wxDebugMsg("focus proc from frame %ld\n",(long)frame);
780 // TODO
dfe1eee3
VZ
781 // wxFrame *frame = (wxFrame *)clientData;
782 // frame->GetEventHandler()->OnSetFocus();
4bb6408c
JS
783}
784
785/* MATTEW: Used to insure that hide-&-show within an event cycle works */
dfe1eee3 786static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
2d120f83 787 XCrossingEvent * event)
4bb6408c 788{
dfe1eee3
VZ
789 wxFrame *frame = (wxFrame *)wxGetWindowFromTable((Widget)clientData);
790
2d120f83
JS
791 if (frame) {
792 XEvent *e = (XEvent *)event;
dfe1eee3 793
2d120f83
JS
794 if (e->xany.type == MapNotify)
795 {
796 // Iconize fix
797 XtVaSetValues(frameShell, XmNiconic, (Boolean)False, NULL);
798 if (!frame->GetVisibleStatus())
799 {
800 /* We really wanted this to be hidden! */
801 XtUnmapWidget((Widget) frame->GetShellWidget());
802 }
803 }
804 else if (e->xany.type == UnmapNotify)
805 // Iconize fix
806 XtVaSetValues(frameShell, XmNiconic, (Boolean)True, NULL);
4bb6408c 807 }
4bb6408c
JS
808}
809
810//// Motif-specific
811bool wxFrame::PreResize()
812{
1ccbb61a 813#if wxUSE_TOOLBAR
2d120f83 814 PositionToolBar();
1ccbb61a 815#endif // wxUSE_TOOLBAR
1c4f8f8d
VZ
816
817#if wxUSE_STATUSBAR
2d120f83 818 PositionStatusBar();
1c4f8f8d
VZ
819#endif // wxUSE_STATUSBAR
820
2d120f83 821 return TRUE;
4bb6408c
JS
822}
823
50414e24
JS
824WXWidget wxFrame::GetClientWidget() const
825{
2d120f83 826 return m_clientArea;
50414e24
JS
827}
828
af111fc3 829void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize))
0d57be45
JS
830{
831 // TODO
832}
833
834void wxFrame::ChangeBackgroundColour()
835{
621793f4
JS
836 if (GetClientWidget())
837 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
0d57be45
JS
838}
839
840void wxFrame::ChangeForegroundColour()
841{
621793f4
JS
842 if (GetClientWidget())
843 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
0d57be45
JS
844}
845
af111fc3 846void wxCloseFrameCallback(Widget WXUNUSED(widget), XtPointer client_data, XmAnyCallbackStruct *WXUNUSED(cbs))
4bb6408c 847{
2d120f83 848 wxFrame *frame = (wxFrame *)client_data;
dfe1eee3 849
2d120f83
JS
850 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId());
851 closeEvent.SetEventObject(frame);
dfe1eee3 852
2d120f83
JS
853 // May delete the frame (with delayed deletion)
854 frame->GetEventHandler()->ProcessEvent(closeEvent);
4bb6408c 855}
0d57be45 856