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