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