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