]> git.saurik.com Git - wxWidgets.git/blame - src/motif/frame.cpp
*** empty log message ***
[wxWidgets.git] / src / motif / frame.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: frame.cpp
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
12#ifdef __GNUG__
13#pragma implementation "frame.h"
14#endif
15
16#include "wx/frame.h"
17#include "wx/statusbr.h"
18#include "wx/toolbar.h"
19#include "wx/menuitem.h"
20#include "wx/menu.h"
21#include "wx/dcclient.h"
22#include "wx/dialog.h"
23#include "wx/settings.h"
24#include "wx/app.h"
25#include "wx/utils.h"
26
27#if defined(__ultrix) || defined(__sgi)
28#include <Xm/Frame.h>
29#endif
30
31#include <Xm/Xm.h>
32#include <X11/Shell.h>
33#if XmVersion >= 1002
34#include <Xm/XmAll.h>
35#else
36#include <Xm/Frame.h>
37#endif
38#include <Xm/MwmUtil.h>
39#include <Xm/BulletinB.h>
40#include <Xm/Form.h>
41#include <Xm/MainW.h>
42#include <Xm/RowColumn.h>
43#include <Xm/Label.h>
44#include <Xm/AtomMgr.h>
45#include <Xm/LabelG.h>
46#include <Xm/Frame.h>
47#if XmVersion > 1000
48#include <Xm/Protocols.h>
49#endif
50
51#include "wx/motif/private.h"
52
53void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs);
dfe1eee3 54void wxFrameFocusProc(Widget workArea, XtPointer clientData,
4bb6408c 55 XmAnyCallbackStruct *cbs);
dfe1eee3 56static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
2d120f83 57 XCrossingEvent * event);
4bb6408c
JS
58
59extern wxList wxModelessWindows;
60extern wxList wxPendingDelete;
61
62// TODO: this should be tidied so that any frame can be the
63// top frame
64static bool wxTopLevelUsed = FALSE;
65
66#if !USE_SHARED_LIBRARY
c0854a08 67BEGIN_EVENT_TABLE(wxFrame, wxWindow)
8e877c19
RR
68 EVT_SIZE(wxFrame::OnSize)
69 EVT_ACTIVATE(wxFrame::OnActivate)
70 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
71 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
72 EVT_IDLE(wxFrame::OnIdle)
73 EVT_CLOSE(wxFrame::OnCloseWindow)
4bb6408c
JS
74END_EVENT_TABLE()
75
c0854a08 76IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
4bb6408c
JS
77#endif
78
47d67540 79#if wxUSE_NATIVE_STATUSBAR
4bb6408c
JS
80bool wxFrame::m_useNativeStatusBar = TRUE;
81#else
82bool wxFrame::m_useNativeStatusBar = FALSE;
83#endif
84
85wxFrame::wxFrame()
86{
1ccbb61a 87#if wxUSE_TOOLBAR
4bb6408c 88 m_frameToolBar = NULL ;
1ccbb61a
VZ
89#endif // wxUSE_TOOLBAR
90
4bb6408c
JS
91 m_frameMenuBar = NULL;
92 m_frameStatusBar = NULL;
dfe1eee3 93
da175b2c 94 m_parent = NULL;
4bb6408c 95 m_iconized = FALSE;
dfe1eee3 96
4bb6408c
JS
97 //// Motif-specific
98 m_frameShell = (WXWidget) NULL;
99 m_frameWidget = (WXWidget) NULL;;
100 m_workArea = (WXWidget) NULL;;
101 m_clientArea = (WXWidget) NULL;;
102 m_visibleStatus = TRUE;
103 m_title = "";
104}
105
106bool wxFrame::Create(wxWindow *parent,
2d120f83
JS
107 wxWindowID id,
108 const wxString& title,
109 const wxPoint& pos,
110 const wxSize& size,
111 long style,
112 const wxString& name)
4bb6408c 113{
2d120f83
JS
114 if (!parent)
115 wxTopLevelWindows.Append(this);
dfe1eee3 116
2d120f83 117 SetName(name);
dfe1eee3 118
2d120f83
JS
119 m_windowStyle = style;
120 m_frameMenuBar = NULL;
1ccbb61a 121#if wxUSE_TOOLBAR
2d120f83 122 m_frameToolBar = NULL ;
1ccbb61a 123#endif // wxUSE_TOOLBAR
2d120f83 124 m_frameStatusBar = NULL;
dfe1eee3 125
2d120f83
JS
126 //// Motif-specific
127 m_frameShell = (WXWidget) NULL;
128 m_frameWidget = (WXWidget) NULL;;
129 m_workArea = (WXWidget) NULL;;
130 m_clientArea = (WXWidget) NULL;;
131 m_visibleStatus = TRUE;
132 m_title = "";
dfe1eee3 133
2d120f83
JS
134 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE);
135 m_foregroundColour = *wxBLACK;
da175b2c 136 m_font = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
dfe1eee3 137
2d120f83
JS
138 if ( id > -1 )
139 m_windowId = id;
140 else
141 m_windowId = (int)NewControlId();
dfe1eee3 142
2d120f83 143 if (parent) parent->AddChild(this);
dfe1eee3 144
2d120f83 145 wxModelessWindows.Append(this);
dfe1eee3 146
447a039f
MB
147 int x = pos.x, y = pos.y;
148 int width = size.x, height = size.y;
149
150 // Set reasonable values for position and size if defaults have
151 // been requested
152 //
153 // MB TODO: something better than these arbitrary values ?
154 //
155 if ( width == -1 ) width = 400;
156 if ( height = -1 ) height = 400;
157
158 int displayW, displayH;
159 wxDisplaySize( &displayW, &displayH );
160
161 if ( x == -1 )
162 {
163 x = (displayW - width) / 2;
164 if (x < 10) x = 10;
165 }
166 if ( y == -1 )
167 {
168 y = (displayH - height) / 2;
169 if (y < 10) y = 10;
170 }
171
2d120f83 172 if (wxTopLevelUsed)
31528cd3 173 {
2d120f83 174 // Change suggested by Matthew Flatt
31528cd3
VZ
175 m_frameShell = (WXWidget)XtAppCreateShell
176 (
177 name,
178 wxTheApp->GetClassName(),
179 topLevelShellWidgetClass,
180 (Display*) wxGetDisplay(),
181 NULL,
182 0
183 );
184 }
2d120f83
JS
185 else
186 {
187 m_frameShell = wxTheApp->GetTopLevelWidget();
188 wxTopLevelUsed = TRUE;
189 }
dfe1eee3
VZ
190
191 XtVaSetValues((Widget) m_frameShell,
2d120f83
JS
192 // Allows menu to resize
193 XmNallowShellResize, True,
194 XmNdeleteResponse, XmDO_NOTHING,
195 XmNmappedWhenManaged, False,
196 XmNiconic, (style & wxICONIZE) ? TRUE : FALSE,
197 NULL);
dfe1eee3 198
2d120f83 199 if (!title.IsNull())
dfe1eee3 200 XtVaSetValues((Widget) m_frameShell,
2d120f83
JS
201 XmNtitle, (const char*) title,
202 NULL);
dfe1eee3 203
2d120f83
JS
204 m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window",
205 xmMainWindowWidgetClass, (Widget) m_frameShell,
206 XmNresizePolicy, XmRESIZE_NONE,
207 NULL);
dfe1eee3 208
2d120f83
JS
209 m_workArea = (WXWidget) XtVaCreateWidget("form",
210 xmFormWidgetClass, (Widget) m_frameWidget,
211 XmNresizePolicy, XmRESIZE_NONE,
212 NULL);
dfe1eee3 213
2d120f83
JS
214 m_clientArea = (WXWidget) XtVaCreateWidget("client",
215 xmBulletinBoardWidgetClass, (Widget) m_workArea,
216 XmNmarginWidth, 0,
217 XmNmarginHeight, 0,
218 XmNrightAttachment, XmATTACH_FORM,
219 XmNleftAttachment, XmATTACH_FORM,
220 XmNtopAttachment, XmATTACH_FORM,
221 XmNbottomAttachment, XmATTACH_FORM,
222 // XmNresizePolicy, XmRESIZE_ANY,
223 NULL);
0492c5a0 224
31528cd3
VZ
225 wxLogDebug("Created frame (0x%08x) with work area 0x%08x and client "
226 "area 0x%08x", m_frameWidget, m_workArea, m_clientArea);
227
2e35f56f
JS
228 XtAddEventHandler((Widget) m_clientArea, ExposureMask,FALSE,
229 wxUniversalRepaintProc, (XtPointer) this);
dfe1eee3 230
2d120f83
JS
231 XtVaSetValues((Widget) m_frameWidget,
232 XmNworkWindow, (Widget) m_workArea,
233 NULL);
dfe1eee3 234
2d120f83
JS
235 XtManageChild((Widget) m_clientArea);
236 XtManageChild((Widget) m_workArea);
dfe1eee3 237
2d120f83 238 wxAddWindowToTable((Widget) m_workArea, this);
dfe1eee3 239
2d120f83 240 XtTranslations ptr ;
dfe1eee3 241
2d120f83
JS
242 XtOverrideTranslations((Widget) m_workArea,
243 ptr = XtParseTranslationTable("<Configure>: resize()"));
dfe1eee3 244
2d120f83 245 XtFree((char *)ptr);
dfe1eee3
VZ
246
247 XtAddCallback((Widget) m_workArea, XmNfocusCallback,
2d120f83 248 (XtCallbackProc)wxFrameFocusProc, (XtPointer)this);
dfe1eee3 249
2d120f83
JS
250 /* Part of show-&-hide fix */
251 XtAddEventHandler((Widget) m_frameShell, StructureNotifyMask,
252 False, (XtEventHandler)wxFrameMapProc,
253 (XtPointer)m_workArea);
dfe1eee3 254
2d120f83
JS
255 if (x > -1)
256 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
257 if (y > -1)
258 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
259 if (width > -1)
260 XtVaSetValues((Widget) m_frameShell, XmNwidth, width, NULL);
261 if (height > -1)
262 XtVaSetValues((Widget) m_frameShell, XmNheight, height, NULL);
dfe1eee3 263
2d120f83 264 m_mainWidget = m_frameWidget;
dfe1eee3 265
2d120f83 266 ChangeFont(FALSE);
dfe1eee3 267
2d120f83
JS
268 // This patch comes from Torsten Liermann lier@lier1.muc.de
269 if (XmIsMotifWMRunning( (Widget) m_frameShell ))
270 {
271 int decor = 0 ;
272 if (style & wxRESIZE_BORDER)
273 decor |= MWM_DECOR_RESIZEH ;
274 if (style & wxSYSTEM_MENU)
275 decor |= MWM_DECOR_MENU;
276 if ((style & wxCAPTION) ||
277 (style & wxTINY_CAPTION_HORIZ) ||
278 (style & wxTINY_CAPTION_VERT))
279 decor |= MWM_DECOR_TITLE;
280 if (style & wxTHICK_FRAME)
281 decor |= MWM_DECOR_BORDER;
282 if (style & wxTHICK_FRAME)
283 decor |= MWM_DECOR_BORDER;
284 if (style & wxMINIMIZE_BOX)
285 decor |= MWM_DECOR_MINIMIZE;
286 if (style & wxMAXIMIZE_BOX)
287 decor |= MWM_DECOR_MAXIMIZE;
288 XtVaSetValues((Widget) m_frameShell,XmNmwmDecorations,decor,NULL) ;
289 }
290 // This allows non-Motif window managers to support at least the
291 // no-decorations case.
292 else
293 {
294 if (style == 0)
295 XtVaSetValues((Widget) m_frameShell,XmNoverrideRedirect,TRUE,NULL);
296 }
297 XtRealizeWidget((Widget) m_frameShell);
dfe1eee3 298
2d120f83
JS
299 // Intercept CLOSE messages from the window manager
300 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay((Widget) m_frameShell), "WM_DELETE_WINDOW", False);
4bb6408c 301#if (XmREVISION > 1 || XmVERSION > 1)
2d120f83 302 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (XtPointer)this);
4bb6408c
JS
303#else
304#if XmREVISION == 1
2d120f83 305 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (caddr_t)this);
4bb6408c 306#else
2d120f83 307 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this);
4bb6408c
JS
308#endif
309#endif
dfe1eee3 310
2d120f83 311 ChangeBackgroundColour();
dfe1eee3 312
2d120f83 313 PreResize();
dfe1eee3 314
2d120f83
JS
315 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
316 sizeEvent.SetEventObject(this);
dfe1eee3 317
2d120f83 318 GetEventHandler()->ProcessEvent(sizeEvent);
dfe1eee3 319
2d120f83 320 return TRUE;
4bb6408c
JS
321}
322
323wxFrame::~wxFrame()
324{
3ab377bd
MB
325 m_isBeingDeleted = TRUE;
326
2e35f56f
JS
327 if (m_clientArea)
328 XtRemoveEventHandler((Widget) m_clientArea, ExposureMask, FALSE,
329 wxUniversalRepaintProc, (XtPointer) this);
330
2d120f83
JS
331 if (GetMainWidget())
332 Show(FALSE);
0492c5a0 333
2d120f83
JS
334 if (m_frameMenuBar)
335 {
336 m_frameMenuBar->DestroyMenuBar();
dfe1eee3 337
2d120f83 338 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
4bb6408c 339#if MOTIF_MENUBAR_DELETE_FIX
2d120f83 340 GetMenuBar()->SetMainWidget((WXWidget) NULL);
4bb6408c 341#endif
2d120f83
JS
342 delete m_frameMenuBar;
343 m_frameMenuBar = NULL;
344 }
dfe1eee3 345
2d120f83
JS
346 wxTopLevelWindows.DeleteObject(this);
347 wxModelessWindows.DeleteObject(this);
dfe1eee3 348
2d120f83
JS
349 if (m_frameStatusBar)
350 delete m_frameStatusBar;
dfe1eee3 351
2d120f83 352 DestroyChildren();
dfe1eee3 353
2d120f83
JS
354 /*
355 int i;
356 for (i = 0; i < wxMAX_STATUS; i++)
4bb6408c 357 if (statusTextWidget[i])
2d120f83 358 XtDestroyWidget (statusTextWidget[i]);
dfe1eee3 359
2d120f83
JS
360 if (statusLineForm)
361 XtDestroyWidget (statusLineForm);
dfe1eee3 362
2d120f83
JS
363 if (statusLineWidget)
364 XtDestroyWidget (statusLineWidget);
365 */
dfe1eee3 366
2d120f83 367 if (m_workArea)
4bb6408c 368 {
2d120f83 369 wxDeleteWindowFromTable((Widget) m_workArea);
dfe1eee3 370
2d120f83 371 XtDestroyWidget ((Widget) m_workArea);
4bb6408c 372 }
dfe1eee3 373
2d120f83
JS
374 if (m_frameWidget)
375 {
376 wxDeleteWindowFromTable((Widget) m_frameWidget);
377 XtDestroyWidget ((Widget) m_frameWidget);
378 }
dfe1eee3 379
2d120f83
JS
380 if (m_frameShell)
381 XtDestroyWidget ((Widget) m_frameShell);
dfe1eee3 382
2d120f83 383 SetMainWidget((WXWidget) NULL);
dfe1eee3 384
2d120f83 385 /* Check if it's the last top-level window */
dfe1eee3 386
2d120f83
JS
387 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
388 {
389 wxTheApp->SetTopWindow(NULL);
dfe1eee3 390
2d120f83
JS
391 if (wxTheApp->GetExitOnFrameDelete())
392 {
393 // Signal to the app that we're going to close
394 wxTheApp->ExitMainLoop();
395 }
396 }
dfe1eee3 397
4bb6408c
JS
398}
399
400// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
401void wxFrame::GetClientSize(int *x, int *y) const
402{
2d120f83
JS
403 Dimension xx, yy;
404 XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL);
dfe1eee3 405
2d120f83
JS
406 if (m_frameStatusBar)
407 {
408 int sbw, sbh;
409 m_frameStatusBar->GetSize(& sbw, & sbh);
410 yy -= sbh;
411 }
1ccbb61a 412#if wxUSE_TOOLBAR
2d120f83
JS
413 if (m_frameToolBar)
414 {
415 int tbw, tbh;
416 m_frameToolBar->GetSize(& tbw, & tbh);
417 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
418 xx -= tbw;
419 else
420 yy -= tbh;
421 }
1ccbb61a 422#endif // wxUSE_TOOLBAR
2d120f83
JS
423 /*
424 if (GetMenuBar() != (wxMenuBar*) NULL)
425 {
4bb6408c
JS
426 // it seems that if a frame holds a panel, the menu bar size
427 // gets automatically taken care of --- grano@cs.helsinki.fi 4.4.95
428 bool hasSubPanel = FALSE;
c0ed460c 429 for(wxNode* node = GetChildren().First(); node; node = node->Next())
4bb6408c 430 {
2d120f83
JS
431 wxWindow *win = (wxWindow *)node->Data();
432 hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog)));
dfe1eee3 433
4bb6408c 434 if (hasSubPanel)
2d120f83
JS
435 break;
436 }
437 if (! hasSubPanel) {
4bb6408c
JS
438 Dimension ys;
439 XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL);
440 yy -= ys;
2d120f83
JS
441 }
442 }
443 */
dfe1eee3 444
2d120f83 445 *x = xx; *y = yy;
4bb6408c
JS
446}
447
448// Set the client size (i.e. leave the calculation of borders etc.
449// to wxWindows)
bfc6fde4 450void wxFrame::DoSetClientSize(int width, int height)
4bb6408c 451{
2d120f83
JS
452 // Calculate how large the new main window should be
453 // by finding the difference between the client area and the
454 // main window area, and adding on to the new client area
455 if (width > -1)
456 XtVaSetValues((Widget) m_workArea, XmNwidth, width, NULL);
dfe1eee3 457
2d120f83 458 if (height > -1)
a4294b78 459 {
2d120f83
JS
460 if (m_frameStatusBar)
461 {
462 int sbw, sbh;
463 m_frameStatusBar->GetSize(& sbw, & sbh);
464 height += sbh;
465 }
1ccbb61a 466#if wxUSE_TOOLBAR
2d120f83
JS
467 if (m_frameToolBar)
468 {
469 int tbw, tbh;
470 m_frameToolBar->GetSize(& tbw, & tbh);
471 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
472 width += tbw;
473 else
474 height += tbh;
475 }
1ccbb61a 476#endif // wxUSE_TOOLBAR
dfe1eee3 477
2d120f83 478 XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL);
a4294b78 479 }
2d120f83 480 PreResize();
dfe1eee3 481
2d120f83
JS
482 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
483 sizeEvent.SetEventObject(this);
dfe1eee3 484
2d120f83 485 GetEventHandler()->ProcessEvent(sizeEvent);
dfe1eee3 486
4bb6408c
JS
487}
488
489void wxFrame::GetSize(int *width, int *height) const
490{
2d120f83
JS
491 Dimension xx, yy;
492 XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL);
493 *width = xx; *height = yy;
4bb6408c
JS
494}
495
496void wxFrame::GetPosition(int *x, int *y) const
497{
498 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
499 next_parent = XtWindow((Widget) m_frameShell),
500 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
dfe1eee3 501
4bb6408c
JS
502 // search for the parent that is child of ROOT, because the WM may
503 // reparent twice and notify only the next parent (like FVWM)
504 while (next_parent != root) {
2d120f83
JS
505 Window *theChildren; unsigned int n;
506 parent_window = next_parent;
507 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
508 &next_parent, &theChildren, &n);
509 XFree(theChildren); // not needed
4bb6408c
JS
510 }
511 int xx, yy; unsigned int dummy;
512 XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root,
2d120f83 513 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
4bb6408c
JS
514 if (x) *x = xx;
515 if (y) *y = yy;
516}
517
bfc6fde4 518void wxFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags)
4bb6408c 519{
2d120f83
JS
520 if (x > -1)
521 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
522 if (y > -1)
523 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
524 if (width > -1)
525 XtVaSetValues((Widget) m_frameWidget, XmNwidth, width, NULL);
526 if (height > -1)
527 XtVaSetValues((Widget) m_frameWidget, XmNheight, height, NULL);
dfe1eee3 528
2d120f83
JS
529 if (!(height == -1 && width == -1))
530 {
531 PreResize();
dfe1eee3 532
2d120f83
JS
533 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
534 sizeEvent.SetEventObject(this);
dfe1eee3 535
2d120f83
JS
536 GetEventHandler()->ProcessEvent(sizeEvent);
537 }
4bb6408c
JS
538}
539
540bool wxFrame::Show(bool show)
541{
2d120f83
JS
542 if (!m_frameShell)
543 return wxWindow::Show(show);
dfe1eee3 544
2d120f83 545 m_visibleStatus = show; /* show-&-hide fix */
dfe1eee3 546
2d120f83
JS
547 m_isShown = show;
548 if (show) {
549 XtMapWidget((Widget) m_frameShell);
550 XRaiseWindow(XtDisplay((Widget) m_frameShell), XtWindow((Widget) m_frameShell));
551 } else {
552 XtUnmapWidget((Widget) m_frameShell);
553 // XmUpdateDisplay(wxTheApp->topLevel); // Experimental: may be responsible for crashes
554 }
555 return TRUE;
4bb6408c
JS
556}
557
558void wxFrame::Iconize(bool iconize)
559{
2d120f83
JS
560 if (!iconize)
561 Show(TRUE);
dfe1eee3 562
2d120f83
JS
563 if (m_frameShell)
564 XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL);
4bb6408c
JS
565}
566
567// Equivalent to maximize/restore in Windows
568void wxFrame::Maximize(bool maximize)
569{
2d120f83 570 Show(TRUE);
dfe1eee3 571
2d120f83
JS
572 if (maximize && m_frameShell)
573 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
4bb6408c
JS
574}
575
576bool wxFrame::IsIconized() const
577{
2d120f83
JS
578 if (!m_frameShell)
579 return FALSE;
dfe1eee3 580
2d120f83
JS
581 Boolean iconic;
582 XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL);
583 return iconic;
4bb6408c
JS
584}
585
6f63ec3f
JS
586// Is it maximized?
587bool wxFrame::IsMaximized(void) const
588{
589 // No maximizing in Motif (?)
590 return FALSE;
591}
592
4bb6408c
JS
593void wxFrame::SetTitle(const wxString& title)
594{
2d120f83
JS
595 if (title == m_title)
596 return;
dfe1eee3 597
2d120f83 598 m_title = title;
dfe1eee3 599
2d120f83 600 if (!title.IsNull())
dfe1eee3 601 XtVaSetValues((Widget) m_frameShell,
2d120f83
JS
602 XmNtitle, (const char*) title,
603 XmNiconName, (const char*) title,
604 NULL);
4bb6408c
JS
605}
606
607void wxFrame::SetIcon(const wxIcon& icon)
608{
2d120f83 609 m_icon = icon;
dfe1eee3 610
2d120f83
JS
611 if (!m_frameShell)
612 return;
dfe1eee3 613
2d120f83
JS
614 if (!icon.Ok() || !icon.GetPixmap())
615 return;
dfe1eee3 616
2d120f83 617 XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL);
4bb6408c
JS
618}
619
620wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
2d120f83 621 const wxString& name)
4bb6408c
JS
622{
623 wxStatusBar *statusBar = NULL;
dfe1eee3 624
4bb6408c
JS
625 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20),
626 style, name);
dfe1eee3 627
4bb6408c
JS
628 // Set the height according to the font and the border size
629 wxClientDC dc(statusBar);
c0ed460c 630 dc.SetFont(statusBar->GetFont());
dfe1eee3 631
4bb6408c
JS
632 long x, y;
633 dc.GetTextExtent("X", &x, &y);
dfe1eee3 634
4bb6408c 635 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
dfe1eee3 636
4bb6408c 637 statusBar->SetSize(-1, -1, 100, height);
dfe1eee3 638
4bb6408c
JS
639 statusBar->SetFieldsCount(number);
640 return statusBar;
641}
642
643wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id,
2d120f83 644 const wxString& name)
4bb6408c 645{
2d120f83 646 // Calling CreateStatusBar twice is an error.
dfe1eee3 647 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE,
2d120f83 648 "recreating status bar in wxFrame" );
dfe1eee3 649
2d120f83
JS
650 m_frameStatusBar = OnCreateStatusBar(number, style, id,
651 name);
652 if ( m_frameStatusBar )
653 {
654 PositionStatusBar();
655 return m_frameStatusBar;
656 }
657 else
658 return NULL;
4bb6408c
JS
659}
660
661void wxFrame::SetStatusText(const wxString& text, int number)
662{
2d120f83 663 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" );
dfe1eee3 664
2d120f83 665 m_frameStatusBar->SetStatusText(text, number);
4bb6408c
JS
666}
667
668void wxFrame::SetStatusWidths(int n, const int widths_field[])
669{
2d120f83 670 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" );
dfe1eee3 671
2d120f83
JS
672 m_frameStatusBar->SetStatusWidths(n, widths_field);
673 PositionStatusBar();
4bb6408c
JS
674}
675
676void wxFrame::PositionStatusBar()
677{
50414e24 678 if (!m_frameStatusBar)
2d120f83 679 return;
dfe1eee3 680
4bb6408c
JS
681 int w, h;
682 GetClientSize(&w, &h);
683 int sw, sh;
684 m_frameStatusBar->GetSize(&sw, &sh);
dfe1eee3 685
4bb6408c
JS
686 // Since we wish the status bar to be directly under the client area,
687 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
89c7e962 688 m_frameStatusBar->SetSize(0, h, w, sh);
4bb6408c
JS
689}
690
691WXWidget wxFrame::GetMenuBarWidget() const
692{
2d120f83
JS
693 if (GetMenuBar())
694 return GetMenuBar()->GetMainWidget();
695 else
696 return (WXWidget) NULL;
4bb6408c
JS
697}
698
699void wxFrame::SetMenuBar(wxMenuBar *menuBar)
700{
701 if (!menuBar)
702 {
703 m_frameMenuBar = NULL;
704 return;
705 }
dfe1eee3 706
4bb6408c 707 // Currently can't set it twice
2d120f83 708 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
dfe1eee3 709
621793f4 710 if (m_frameMenuBar)
4bb6408c 711 {
621793f4
JS
712 m_frameMenuBar->DestroyMenuBar();
713 delete m_frameMenuBar;
4bb6408c 714 }
dfe1eee3 715
621793f4
JS
716 m_frameMenuBar = menuBar;
717 m_frameMenuBar->CreateMenuBar(this);
4bb6408c
JS
718}
719
720void wxFrame::Fit()
721{
2d120f83
JS
722 // Work out max. size
723 wxNode *node = GetChildren().First();
724 int max_width = 0;
725 int max_height = 0;
726 while (node)
4bb6408c 727 {
2d120f83
JS
728 // Find a child that's a subwindow, but not a dialog box.
729 wxWindow *win = (wxWindow *)node->Data();
dfe1eee3 730
2d120f83
JS
731 if (!win->IsKindOf(CLASSINFO(wxFrame)) &&
732 !win->IsKindOf(CLASSINFO(wxDialog)))
733 {
734 int width, height;
735 int x, y;
736 win->GetSize(&width, &height);
737 win->GetPosition(&x, &y);
dfe1eee3 738
2d120f83
JS
739 if ((x + width) > max_width)
740 max_width = x + width;
741 if ((y + height) > max_height)
742 max_height = y + height;
743 }
744 node = node->Next();
4bb6408c 745 }
2d120f83 746 SetClientSize(max_width, max_height);
4bb6408c
JS
747}
748
749// Responds to colour changes, and passes event on to children.
750void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
751{
752 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
753 Refresh();
dfe1eee3 754
4bb6408c
JS
755 if ( m_frameStatusBar )
756 {
757 wxSysColourChangedEvent event2;
758 event2.SetEventObject( m_frameStatusBar );
759 m_frameStatusBar->ProcessEvent(event2);
760 }
dfe1eee3 761
4bb6408c
JS
762 // Propagate the event to the non-top-level children
763 wxWindow::OnSysColourChanged(event);
764}
765
766// Default resizing behaviour - if only ONE subwindow,
767// resize to client rectangle size
768void wxFrame::OnSize(wxSizeEvent& event)
769{
2d120f83
JS
770 // if we're using constraints - do use them
771#if wxUSE_CONSTRAINTS
4bb6408c 772 if ( GetAutoLayout() ) {
2d120f83
JS
773 Layout();
774 return;
4bb6408c 775 }
2d120f83 776#endif
dfe1eee3 777
2d120f83
JS
778 // do we have _exactly_ one child?
779 wxWindow *child = NULL;
780 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
4bb6408c 781 {
2d120f83
JS
782 wxWindow *win = (wxWindow *)node->Data();
783 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
dfe1eee3 784 !win->IsKindOf(CLASSINFO(wxDialog)) &&
1ccbb61a
VZ
785 (win != GetStatusBar())
786#if wxUSE_TOOLBAR
787 && (win != GetToolBar())
788#endif // wxUSE_TOOLBAR
789 )
2d120f83
JS
790 {
791 if ( child )
792 return; // it's our second subwindow - nothing to do
793 child = win;
794 }
795 }
dfe1eee3 796
2d120f83
JS
797 if ( child ) {
798 // we have exactly one child - set it's size to fill the whole frame
799 int clientW, clientH;
800 GetClientSize(&clientW, &clientH);
dfe1eee3 801
2d120f83
JS
802 int x = 0;
803 int y = 0;
dfe1eee3 804
2d120f83 805 child->SetSize(x, y, clientW, clientH);
4bb6408c 806 }
4bb6408c
JS
807}
808
809// Default activation behaviour - set the focus for the first child
810// subwindow found.
811void wxFrame::OnActivate(wxActivateEvent& event)
812{
2d120f83 813 for(wxNode *node = GetChildren().First(); node; node = node->Next())
4bb6408c 814 {
2d120f83
JS
815 // Find a child that's a subwindow, but not a dialog box.
816 wxWindow *child = (wxWindow *)node->Data();
817 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
818 !child->IsKindOf(CLASSINFO(wxDialog)))
819 {
820 child->SetFocus();
821 return;
822 }
4bb6408c 823 }
4bb6408c
JS
824}
825
e3065973 826// The default implementation for the close window event.
4bb6408c
JS
827// OnClose for backward compatibility.
828
829void wxFrame::OnCloseWindow(wxCloseEvent& event)
830{
e3065973 831 this->Destroy();
4bb6408c
JS
832}
833
834// Destroy the window (delayed, if a managed window)
835bool wxFrame::Destroy()
836{
2d120f83
JS
837 if (!wxPendingDelete.Member(this))
838 wxPendingDelete.Append(this);
839 return TRUE;
4bb6408c
JS
840}
841
842// Default menu selection behaviour - display a help string
843void wxFrame::OnMenuHighlight(wxMenuEvent& event)
844{
2d120f83 845 if (GetStatusBar())
4bb6408c 846 {
2d120f83
JS
847 if (event.GetMenuId() == -1)
848 SetStatusText("");
849 else
850 {
851 wxMenuBar *menuBar = GetMenuBar();
852 if (menuBar)
853 {
854 wxString helpString(menuBar->GetHelpString(event.GetMenuId()));
855 if (helpString != "")
856 SetStatusText(helpString);
857 }
858 }
4bb6408c 859 }
4bb6408c
JS
860}
861
862wxMenuBar *wxFrame::GetMenuBar() const
863{
2d120f83 864 return m_frameMenuBar;
4bb6408c
JS
865}
866
867void wxFrame::Centre(int direction)
868{
2d120f83
JS
869 int display_width, display_height, width, height, x, y;
870 wxDisplaySize(&display_width, &display_height);
dfe1eee3 871
2d120f83
JS
872 GetSize(&width, &height);
873 GetPosition(&x, &y);
dfe1eee3 874
2d120f83
JS
875 if (direction & wxHORIZONTAL)
876 x = (int)((display_width - width)/2);
877 if (direction & wxVERTICAL)
878 y = (int)((display_height - height)/2);
dfe1eee3 879
2d120f83 880 SetSize(x, y, width, height);
4bb6408c
JS
881}
882
883// Call this to simulate a menu command
884void wxFrame::Command(int id)
885{
2d120f83 886 ProcessCommand(id);
4bb6408c
JS
887}
888
889void wxFrame::ProcessCommand(int id)
890{
c75e6695
VZ
891 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
892 commandEvent.SetInt( id );
893 commandEvent.SetEventObject( this );
894
895 wxMenuBar *bar = GetMenuBar() ;
896 if (!bar)
897 return;
898
899/* TODO: check the menu item if required
900 wxMenuItem *item = bar->FindItemForId(id) ;
901 if (item && item->IsCheckable())
902 {
903 bar->Check(id,!bar->Checked(id)) ;
904 }
905*/
906
6c41a418 907 wxEvtHandler* evtHandler = GetEventHandler();
e702ff0f
JS
908
909 evtHandler->ProcessEvent(commandEvent);
4bb6408c
JS
910}
911
912// Checks if there is a toolbar, and returns the first free client position
913wxPoint wxFrame::GetClientAreaOrigin() const
914{
915 wxPoint pt(0, 0);
1ccbb61a 916#if wxUSE_TOOLBAR
4bb6408c
JS
917 if (GetToolBar())
918 {
919 int w, h;
920 GetToolBar()->GetSize(& w, & h);
dfe1eee3 921
4bb6408c
JS
922 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
923 {
924 pt.x += w;
925 }
926 else
927 {
928 pt.y += h;
929 }
930 }
1ccbb61a
VZ
931#endif // wxUSE_TOOLBAR
932
4bb6408c
JS
933 return pt;
934}
935
87d1e11f
JS
936void wxFrame::ScreenToClient(int *x, int *y) const
937{
938 wxWindow::ScreenToClient(x, y);
dfe1eee3 939
87d1e11f
JS
940 // We may be faking the client origin.
941 // So a window that's really at (0, 30) may appear
942 // (to wxWin apps) to be at (0, 0).
943 wxPoint pt(GetClientAreaOrigin());
944 *x -= pt.x;
945 *y -= pt.y;
946}
947
948void wxFrame::ClientToScreen(int *x, int *y) const
949{
950 // We may be faking the client origin.
951 // So a window that's really at (0, 30) may appear
952 // (to wxWin apps) to be at (0, 0).
953 wxPoint pt1(GetClientAreaOrigin());
954 *x += pt1.x;
955 *y += pt1.y;
dfe1eee3 956
87d1e11f
JS
957 wxWindow::ClientToScreen(x, y);
958}
959
1ccbb61a 960#if wxUSE_TOOLBAR
4bb6408c
JS
961wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
962{
963 wxCHECK_MSG( m_frameToolBar == NULL, FALSE,
2d120f83 964 "recreating toolbar in wxFrame" );
dfe1eee3 965
4bb6408c
JS
966 wxToolBar* toolBar = OnCreateToolBar(style, id, name);
967 if (toolBar)
968 {
969 SetToolBar(toolBar);
970 PositionToolBar();
971 return toolBar;
972 }
973 else
974 {
975 return NULL;
976 }
977}
978
979wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& name)
980{
a4294b78 981 return new wxToolBar(this, id, wxPoint(0, 0), wxSize(100, 24), style, name);
4bb6408c
JS
982}
983
1ccbb61a
VZ
984void wxFrame::SetToolBar(wxToolBar *toolbar)
985{
986 m_frameToolBar = toolbar;
987}
988
989wxToolBar *wxFrame::GetToolBar() const
990{
991 return m_frameToolBar;
992}
993
4bb6408c
JS
994void wxFrame::PositionToolBar()
995{
996 int cw, ch;
dfe1eee3 997
4bb6408c 998 GetClientSize(& cw, &ch);
dfe1eee3 999
4bb6408c
JS
1000 if (GetToolBar())
1001 {
1002 int tw, th;
1003 GetToolBar()->GetSize(& tw, & th);
dfe1eee3 1004
4bb6408c
JS
1005 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
1006 {
1007 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
1008 // means, pretend we don't have toolbar/status bar, so we
1009 // have the original client size.
a4294b78 1010 GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS);
4bb6408c
JS
1011 }
1012 else
1013 {
1014 // Use the 'real' position
1015 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
1016 }
1017 }
1018}
1ccbb61a 1019#endif // wxUSE_TOOLBAR
4bb6408c
JS
1020
1021void wxFrame::CaptureMouse()
1022{
2d120f83
JS
1023 if (m_winCaptured)
1024 return;
dfe1eee3 1025
2d120f83
JS
1026 if (GetMainWidget())
1027 XtAddGrab((Widget) m_frameShell, TRUE, FALSE);
1028 m_winCaptured = TRUE;
4bb6408c
JS
1029}
1030
1031void wxFrame::ReleaseMouse()
1032{
2d120f83
JS
1033 if (!m_winCaptured)
1034 return;
dfe1eee3 1035
2d120f83
JS
1036 if (GetMainWidget())
1037 XtRemoveGrab((Widget) m_frameShell);
1038 m_winCaptured = FALSE;
4bb6408c
JS
1039}
1040
1041void wxFrame::Raise(void)
1042{
1043 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
1044 next_parent = XtWindow((Widget) m_frameShell),
1045 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
4bb6408c
JS
1046 // search for the parent that is child of ROOT, because the WM may
1047 // reparent twice and notify only the next parent (like FVWM)
1048 while (next_parent != root) {
2d120f83
JS
1049 Window *theChildren; unsigned int n;
1050 parent_window = next_parent;
1051 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
1052 &next_parent, &theChildren, &n);
1053 XFree(theChildren); // not needed
4bb6408c
JS
1054 }
1055 XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window);
1056}
1057
1058void wxFrame::Lower(void)
1059{
1060 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
1061 next_parent = XtWindow((Widget) m_frameShell),
1062 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
4bb6408c
JS
1063 // search for the parent that is child of ROOT, because the WM may
1064 // reparent twice and notify only the next parent (like FVWM)
1065 while (next_parent != root) {
2d120f83
JS
1066 Window *theChildren; unsigned int n;
1067 parent_window = next_parent;
1068 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
1069 &next_parent, &theChildren, &n);
1070 XFree(theChildren); // not needed
4bb6408c
JS
1071 }
1072 XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window);
1073}
1074
dfe1eee3 1075void wxFrameFocusProc(Widget workArea, XtPointer clientData,
4bb6408c
JS
1076 XmAnyCallbackStruct *cbs)
1077{
2d120f83
JS
1078 // wxDebugMsg("focus proc from frame %ld\n",(long)frame);
1079 // TODO
dfe1eee3
VZ
1080 // wxFrame *frame = (wxFrame *)clientData;
1081 // frame->GetEventHandler()->OnSetFocus();
4bb6408c
JS
1082}
1083
1084/* MATTEW: Used to insure that hide-&-show within an event cycle works */
dfe1eee3 1085static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
2d120f83 1086 XCrossingEvent * event)
4bb6408c 1087{
dfe1eee3
VZ
1088 wxFrame *frame = (wxFrame *)wxGetWindowFromTable((Widget)clientData);
1089
2d120f83
JS
1090 if (frame) {
1091 XEvent *e = (XEvent *)event;
dfe1eee3 1092
2d120f83
JS
1093 if (e->xany.type == MapNotify)
1094 {
1095 // Iconize fix
1096 XtVaSetValues(frameShell, XmNiconic, (Boolean)False, NULL);
1097 if (!frame->GetVisibleStatus())
1098 {
1099 /* We really wanted this to be hidden! */
1100 XtUnmapWidget((Widget) frame->GetShellWidget());
1101 }
1102 }
1103 else if (e->xany.type == UnmapNotify)
1104 // Iconize fix
1105 XtVaSetValues(frameShell, XmNiconic, (Boolean)True, NULL);
4bb6408c 1106 }
4bb6408c
JS
1107}
1108
1109//// Motif-specific
1110bool wxFrame::PreResize()
1111{
1ccbb61a 1112#if wxUSE_TOOLBAR
2d120f83 1113 PositionToolBar();
1ccbb61a 1114#endif // wxUSE_TOOLBAR
2d120f83
JS
1115 PositionStatusBar();
1116 return TRUE;
4bb6408c
JS
1117}
1118
50414e24
JS
1119WXWidget wxFrame::GetClientWidget() const
1120{
2d120f83 1121 return m_clientArea;
50414e24
JS
1122}
1123
4b5f3fe6 1124void wxFrame::ChangeFont(bool keepOriginalSize)
0d57be45
JS
1125{
1126 // TODO
1127}
1128
1129void wxFrame::ChangeBackgroundColour()
1130{
621793f4
JS
1131 if (GetClientWidget())
1132 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
0d57be45
JS
1133}
1134
1135void wxFrame::ChangeForegroundColour()
1136{
621793f4
JS
1137 if (GetClientWidget())
1138 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
0d57be45
JS
1139}
1140
4bb6408c
JS
1141void wxCloseFrameCallback(Widget widget, XtPointer client_data, XmAnyCallbackStruct *cbs)
1142{
2d120f83 1143 wxFrame *frame = (wxFrame *)client_data;
dfe1eee3 1144
2d120f83
JS
1145 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId());
1146 closeEvent.SetEventObject(frame);
dfe1eee3 1147
2d120f83
JS
1148 // May delete the frame (with delayed deletion)
1149 frame->GetEventHandler()->ProcessEvent(closeEvent);
4bb6408c 1150}
0d57be45 1151