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