]> git.saurik.com Git - wxWidgets.git/blame - src/motif/frame.cpp
Fix/hack 1.
[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
2d120f83
JS
152 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE);
153 m_foregroundColour = *wxBLACK;
da175b2c 154 m_font = wxSystemSettings::GetSystemFont(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;
307 if (style & wxTHICK_FRAME)
308 decor |= MWM_DECOR_BORDER;
309 if (style & wxMINIMIZE_BOX)
310 decor |= MWM_DECOR_MINIMIZE;
311 if (style & wxMAXIMIZE_BOX)
312 decor |= MWM_DECOR_MAXIMIZE;
1c4f8f8d 313 XtVaSetValues((Widget) m_frameShell,XmNmwmDecorations,decor,NULL);
2d120f83
JS
314 }
315 // This allows non-Motif window managers to support at least the
316 // no-decorations case.
317 else
318 {
319 if (style == 0)
320 XtVaSetValues((Widget) m_frameShell,XmNoverrideRedirect,TRUE,NULL);
321 }
322 XtRealizeWidget((Widget) m_frameShell);
dfe1eee3 323
2d120f83
JS
324 // Intercept CLOSE messages from the window manager
325 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay((Widget) m_frameShell), "WM_DELETE_WINDOW", False);
4bb6408c 326#if (XmREVISION > 1 || XmVERSION > 1)
2d120f83 327 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (XtPointer)this);
4bb6408c
JS
328#else
329#if XmREVISION == 1
2d120f83 330 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (caddr_t)this);
4bb6408c 331#else
2d120f83 332 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this);
4bb6408c
JS
333#endif
334#endif
dfe1eee3 335
2d120f83 336 ChangeBackgroundColour();
dfe1eee3 337
2d120f83 338 PreResize();
dfe1eee3 339
2d120f83
JS
340 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
341 sizeEvent.SetEventObject(this);
dfe1eee3 342
2d120f83 343 GetEventHandler()->ProcessEvent(sizeEvent);
dfe1eee3 344
2d120f83 345 return TRUE;
4bb6408c
JS
346}
347
348wxFrame::~wxFrame()
349{
3ab377bd 350 m_isBeingDeleted = TRUE;
da8bed9b 351
2e35f56f 352 if (m_clientArea)
dc1efb1d 353 {
2e35f56f
JS
354 XtRemoveEventHandler((Widget) m_clientArea, ExposureMask, FALSE,
355 wxUniversalRepaintProc, (XtPointer) this);
dc1efb1d
JS
356 XtRemoveEventHandler((Widget) m_clientArea, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask,
357 FALSE,
358 wxFrameEventHandler, (XtPointer) this);
359 wxDeleteWindowFromTable((Widget) m_clientArea);
360 }
2e35f56f 361
2d120f83
JS
362 if (GetMainWidget())
363 Show(FALSE);
0492c5a0 364
2d120f83
JS
365 if (m_frameMenuBar)
366 {
367 m_frameMenuBar->DestroyMenuBar();
dfe1eee3 368
2d120f83 369 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
4bb6408c 370#if MOTIF_MENUBAR_DELETE_FIX
2d120f83 371 GetMenuBar()->SetMainWidget((WXWidget) NULL);
4bb6408c 372#endif
2d120f83
JS
373 delete m_frameMenuBar;
374 m_frameMenuBar = NULL;
375 }
dfe1eee3 376
2d120f83
JS
377 wxTopLevelWindows.DeleteObject(this);
378 wxModelessWindows.DeleteObject(this);
dfe1eee3 379
2d120f83 380 if (m_frameStatusBar)
1c4f8f8d 381 {
2d120f83 382 delete m_frameStatusBar;
1c4f8f8d
VZ
383 m_frameStatusBar = NULL;
384 }
dfe1eee3 385
2d120f83 386 DestroyChildren();
dfe1eee3 387
2d120f83 388 if (m_workArea)
4bb6408c 389 {
2d120f83 390 wxDeleteWindowFromTable((Widget) m_workArea);
dfe1eee3 391
2d120f83 392 XtDestroyWidget ((Widget) m_workArea);
4bb6408c 393 }
dfe1eee3 394
2d120f83
JS
395 if (m_frameWidget)
396 {
397 wxDeleteWindowFromTable((Widget) m_frameWidget);
398 XtDestroyWidget ((Widget) m_frameWidget);
399 }
dfe1eee3 400
2d120f83
JS
401 if (m_frameShell)
402 XtDestroyWidget ((Widget) m_frameShell);
dfe1eee3 403
2d120f83 404 SetMainWidget((WXWidget) NULL);
dfe1eee3 405
2d120f83 406 /* Check if it's the last top-level window */
dfe1eee3 407
2d120f83
JS
408 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
409 {
410 wxTheApp->SetTopWindow(NULL);
dfe1eee3 411
2d120f83
JS
412 if (wxTheApp->GetExitOnFrameDelete())
413 {
414 // Signal to the app that we're going to close
415 wxTheApp->ExitMainLoop();
416 }
417 }
4bb6408c
JS
418}
419
420// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
449f38b5 421void wxFrame::DoGetClientSize(int *x, int *y) const
4bb6408c 422{
2d120f83
JS
423 Dimension xx, yy;
424 XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL);
dfe1eee3 425
2d120f83
JS
426 if (m_frameStatusBar)
427 {
428 int sbw, sbh;
429 m_frameStatusBar->GetSize(& sbw, & sbh);
430 yy -= sbh;
431 }
1ccbb61a 432#if wxUSE_TOOLBAR
2d120f83
JS
433 if (m_frameToolBar)
434 {
435 int tbw, tbh;
436 m_frameToolBar->GetSize(& tbw, & tbh);
437 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
438 xx -= tbw;
439 else
440 yy -= tbh;
441 }
1ccbb61a 442#endif // wxUSE_TOOLBAR
2d120f83
JS
443 /*
444 if (GetMenuBar() != (wxMenuBar*) NULL)
445 {
4bb6408c
JS
446 // it seems that if a frame holds a panel, the menu bar size
447 // gets automatically taken care of --- grano@cs.helsinki.fi 4.4.95
448 bool hasSubPanel = FALSE;
c0ed460c 449 for(wxNode* node = GetChildren().First(); node; node = node->Next())
4bb6408c 450 {
2d120f83
JS
451 wxWindow *win = (wxWindow *)node->Data();
452 hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog)));
dfe1eee3 453
4bb6408c 454 if (hasSubPanel)
2d120f83
JS
455 break;
456 }
457 if (! hasSubPanel) {
4bb6408c
JS
458 Dimension ys;
459 XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL);
460 yy -= ys;
2d120f83
JS
461 }
462 }
463 */
dfe1eee3 464
2d120f83 465 *x = xx; *y = yy;
4bb6408c
JS
466}
467
468// Set the client size (i.e. leave the calculation of borders etc.
469// to wxWindows)
bfc6fde4 470void wxFrame::DoSetClientSize(int width, int height)
4bb6408c 471{
2d120f83
JS
472 // Calculate how large the new main window should be
473 // by finding the difference between the client area and the
474 // main window area, and adding on to the new client area
475 if (width > -1)
476 XtVaSetValues((Widget) m_workArea, XmNwidth, width, NULL);
dfe1eee3 477
2d120f83 478 if (height > -1)
a4294b78 479 {
2d120f83
JS
480 if (m_frameStatusBar)
481 {
482 int sbw, sbh;
483 m_frameStatusBar->GetSize(& sbw, & sbh);
484 height += sbh;
485 }
1ccbb61a 486#if wxUSE_TOOLBAR
2d120f83
JS
487 if (m_frameToolBar)
488 {
489 int tbw, tbh;
490 m_frameToolBar->GetSize(& tbw, & tbh);
491 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
492 width += tbw;
493 else
494 height += tbh;
495 }
1ccbb61a 496#endif // wxUSE_TOOLBAR
dfe1eee3 497
2d120f83 498 XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL);
a4294b78 499 }
2d120f83 500 PreResize();
dfe1eee3 501
2d120f83
JS
502 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
503 sizeEvent.SetEventObject(this);
dfe1eee3 504
2d120f83 505 GetEventHandler()->ProcessEvent(sizeEvent);
dfe1eee3 506
4bb6408c
JS
507}
508
449f38b5 509void wxFrame::DoGetSize(int *width, int *height) const
4bb6408c 510{
2d120f83
JS
511 Dimension xx, yy;
512 XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL);
513 *width = xx; *height = yy;
4bb6408c
JS
514}
515
449f38b5 516void wxFrame::DoGetPosition(int *x, int *y) const
4bb6408c
JS
517{
518 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
519 next_parent = XtWindow((Widget) m_frameShell),
520 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
dfe1eee3 521
4bb6408c
JS
522 // search for the parent that is child of ROOT, because the WM may
523 // reparent twice and notify only the next parent (like FVWM)
524 while (next_parent != root) {
2d120f83
JS
525 Window *theChildren; unsigned int n;
526 parent_window = next_parent;
527 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
528 &next_parent, &theChildren, &n);
529 XFree(theChildren); // not needed
4bb6408c
JS
530 }
531 int xx, yy; unsigned int dummy;
532 XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root,
2d120f83 533 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
4bb6408c
JS
534 if (x) *x = xx;
535 if (y) *y = yy;
536}
537
af111fc3 538void wxFrame::DoSetSize(int x, int y, int width, int height, int WXUNUSED(sizeFlags))
4bb6408c 539{
2d120f83
JS
540 if (x > -1)
541 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
542 if (y > -1)
543 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
544 if (width > -1)
545 XtVaSetValues((Widget) m_frameWidget, XmNwidth, width, NULL);
546 if (height > -1)
547 XtVaSetValues((Widget) m_frameWidget, XmNheight, height, NULL);
dfe1eee3 548
2d120f83
JS
549 if (!(height == -1 && width == -1))
550 {
551 PreResize();
dfe1eee3 552
2d120f83
JS
553 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
554 sizeEvent.SetEventObject(this);
dfe1eee3 555
2d120f83
JS
556 GetEventHandler()->ProcessEvent(sizeEvent);
557 }
4bb6408c
JS
558}
559
560bool wxFrame::Show(bool show)
561{
2d120f83
JS
562 if (!m_frameShell)
563 return wxWindow::Show(show);
dfe1eee3 564
2d120f83 565 m_visibleStatus = show; /* show-&-hide fix */
dfe1eee3 566
2d120f83
JS
567 m_isShown = show;
568 if (show) {
569 XtMapWidget((Widget) m_frameShell);
570 XRaiseWindow(XtDisplay((Widget) m_frameShell), XtWindow((Widget) m_frameShell));
571 } else {
572 XtUnmapWidget((Widget) m_frameShell);
573 // XmUpdateDisplay(wxTheApp->topLevel); // Experimental: may be responsible for crashes
574 }
575 return TRUE;
4bb6408c
JS
576}
577
578void wxFrame::Iconize(bool iconize)
579{
2d120f83
JS
580 if (!iconize)
581 Show(TRUE);
dfe1eee3 582
2d120f83
JS
583 if (m_frameShell)
584 XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL);
4bb6408c
JS
585}
586
1c4f8f8d
VZ
587void wxFrame::Restore()
588{
589 if ( m_frameShell )
590 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
591}
592
4bb6408c
JS
593void wxFrame::Maximize(bool maximize)
594{
2d120f83 595 Show(TRUE);
dfe1eee3 596
1c4f8f8d
VZ
597 if ( maximize )
598 Restore();
4bb6408c
JS
599}
600
601bool wxFrame::IsIconized() const
602{
2d120f83
JS
603 if (!m_frameShell)
604 return FALSE;
dfe1eee3 605
2d120f83
JS
606 Boolean iconic;
607 XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL);
608 return iconic;
4bb6408c
JS
609}
610
6f63ec3f 611// Is it maximized?
1c4f8f8d 612bool wxFrame::IsMaximized() const
6f63ec3f
JS
613{
614 // No maximizing in Motif (?)
615 return FALSE;
616}
617
4bb6408c
JS
618void wxFrame::SetTitle(const wxString& title)
619{
2d120f83
JS
620 if (title == m_title)
621 return;
dfe1eee3 622
2d120f83 623 m_title = title;
dfe1eee3 624
2d120f83 625 if (!title.IsNull())
dfe1eee3 626 XtVaSetValues((Widget) m_frameShell,
1c4f8f8d
VZ
627 XmNtitle, title.c_str(),
628 XmNiconName, title.c_str(),
2d120f83 629 NULL);
4bb6408c
JS
630}
631
632void wxFrame::SetIcon(const wxIcon& icon)
633{
2d120f83 634 m_icon = icon;
dfe1eee3 635
2d120f83
JS
636 if (!m_frameShell)
637 return;
dfe1eee3 638
2d120f83
JS
639 if (!icon.Ok() || !icon.GetPixmap())
640 return;
dfe1eee3 641
2d120f83 642 XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL);
4bb6408c
JS
643}
644
4bb6408c
JS
645void wxFrame::PositionStatusBar()
646{
50414e24 647 if (!m_frameStatusBar)
2d120f83 648 return;
dfe1eee3 649
4bb6408c
JS
650 int w, h;
651 GetClientSize(&w, &h);
652 int sw, sh;
653 m_frameStatusBar->GetSize(&sw, &sh);
dfe1eee3 654
4bb6408c
JS
655 // Since we wish the status bar to be directly under the client area,
656 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
89c7e962 657 m_frameStatusBar->SetSize(0, h, w, sh);
4bb6408c
JS
658}
659
660WXWidget wxFrame::GetMenuBarWidget() const
661{
2d120f83
JS
662 if (GetMenuBar())
663 return GetMenuBar()->GetMainWidget();
664 else
665 return (WXWidget) NULL;
4bb6408c
JS
666}
667
668void wxFrame::SetMenuBar(wxMenuBar *menuBar)
669{
670 if (!menuBar)
671 {
672 m_frameMenuBar = NULL;
673 return;
674 }
dfe1eee3 675
4bb6408c 676 // Currently can't set it twice
2d120f83 677 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
dfe1eee3 678
621793f4 679 if (m_frameMenuBar)
4bb6408c 680 {
621793f4
JS
681 m_frameMenuBar->DestroyMenuBar();
682 delete m_frameMenuBar;
4bb6408c 683 }
dfe1eee3 684
621793f4
JS
685 m_frameMenuBar = menuBar;
686 m_frameMenuBar->CreateMenuBar(this);
4bb6408c
JS
687}
688
4bb6408c
JS
689// Responds to colour changes, and passes event on to children.
690void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
691{
692 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
693 Refresh();
dfe1eee3 694
4bb6408c
JS
695 if ( m_frameStatusBar )
696 {
697 wxSysColourChangedEvent event2;
698 event2.SetEventObject( m_frameStatusBar );
699 m_frameStatusBar->ProcessEvent(event2);
700 }
dfe1eee3 701
4bb6408c
JS
702 // Propagate the event to the non-top-level children
703 wxWindow::OnSysColourChanged(event);
704}
705
4bb6408c
JS
706// Default activation behaviour - set the focus for the first child
707// subwindow found.
708void wxFrame::OnActivate(wxActivateEvent& event)
709{
af111fc3
JS
710 if (!event.GetActive())
711 return;
712
2d120f83 713 for(wxNode *node = GetChildren().First(); node; node = node->Next())
4bb6408c 714 {
2d120f83
JS
715 // Find a child that's a subwindow, but not a dialog box.
716 wxWindow *child = (wxWindow *)node->Data();
717 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
718 !child->IsKindOf(CLASSINFO(wxDialog)))
719 {
720 child->SetFocus();
721 return;
722 }
4bb6408c 723 }
4bb6408c
JS
724}
725
1ccbb61a 726#if wxUSE_TOOLBAR
dfe1eee3 727
1c4f8f8d
VZ
728wxToolBar* wxFrame::CreateToolBar(long style,
729 wxWindowID id,
730 const wxString& name)
4bb6408c 731{
1c4f8f8d 732 if ( wxFrameBase::CreateToolBar(style, id, name) )
4bb6408c 733 {
4bb6408c 734 PositionToolBar();
4bb6408c 735 }
4bb6408c 736
1ccbb61a
VZ
737 return m_frameToolBar;
738}
739
4bb6408c
JS
740void wxFrame::PositionToolBar()
741{
4bb6408c
JS
742 if (GetToolBar())
743 {
1c4f8f8d
VZ
744 int cw, ch;
745 GetClientSize(& cw, &ch);
746
4bb6408c
JS
747 int tw, th;
748 GetToolBar()->GetSize(& tw, & th);
dfe1eee3 749
4bb6408c
JS
750 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
751 {
752 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
753 // means, pretend we don't have toolbar/status bar, so we
754 // have the original client size.
a4294b78 755 GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS);
4bb6408c
JS
756 }
757 else
758 {
759 // Use the 'real' position
760 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
761 }
762 }
763}
1ccbb61a 764#endif // wxUSE_TOOLBAR
4bb6408c 765
1c4f8f8d 766void wxFrame::Raise()
4bb6408c
JS
767{
768 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
769 next_parent = XtWindow((Widget) m_frameShell),
770 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
4bb6408c
JS
771 // search for the parent that is child of ROOT, because the WM may
772 // reparent twice and notify only the next parent (like FVWM)
773 while (next_parent != root) {
2d120f83
JS
774 Window *theChildren; unsigned int n;
775 parent_window = next_parent;
776 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
777 &next_parent, &theChildren, &n);
778 XFree(theChildren); // not needed
4bb6408c
JS
779 }
780 XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window);
781}
782
1c4f8f8d 783void wxFrame::Lower()
4bb6408c
JS
784{
785 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
786 next_parent = XtWindow((Widget) m_frameShell),
787 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
4bb6408c
JS
788 // search for the parent that is child of ROOT, because the WM may
789 // reparent twice and notify only the next parent (like FVWM)
790 while (next_parent != root) {
2d120f83
JS
791 Window *theChildren; unsigned int n;
792 parent_window = next_parent;
793 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
794 &next_parent, &theChildren, &n);
795 XFree(theChildren); // not needed
4bb6408c
JS
796 }
797 XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window);
798}
799
af111fc3
JS
800void wxFrameFocusProc(Widget WXUNUSED(workArea), XtPointer WXUNUSED(clientData),
801 XmAnyCallbackStruct *WXUNUSED(cbs))
4bb6408c 802{
2d120f83
JS
803 // wxDebugMsg("focus proc from frame %ld\n",(long)frame);
804 // TODO
dfe1eee3
VZ
805 // wxFrame *frame = (wxFrame *)clientData;
806 // frame->GetEventHandler()->OnSetFocus();
4bb6408c
JS
807}
808
809/* MATTEW: Used to insure that hide-&-show within an event cycle works */
dfe1eee3 810static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
2d120f83 811 XCrossingEvent * event)
4bb6408c 812{
dfe1eee3
VZ
813 wxFrame *frame = (wxFrame *)wxGetWindowFromTable((Widget)clientData);
814
2d120f83
JS
815 if (frame) {
816 XEvent *e = (XEvent *)event;
dfe1eee3 817
2d120f83
JS
818 if (e->xany.type == MapNotify)
819 {
820 // Iconize fix
821 XtVaSetValues(frameShell, XmNiconic, (Boolean)False, NULL);
822 if (!frame->GetVisibleStatus())
823 {
824 /* We really wanted this to be hidden! */
825 XtUnmapWidget((Widget) frame->GetShellWidget());
826 }
827 }
828 else if (e->xany.type == UnmapNotify)
829 // Iconize fix
830 XtVaSetValues(frameShell, XmNiconic, (Boolean)True, NULL);
4bb6408c 831 }
4bb6408c
JS
832}
833
834//// Motif-specific
835bool wxFrame::PreResize()
836{
1ccbb61a 837#if wxUSE_TOOLBAR
2d120f83 838 PositionToolBar();
1ccbb61a 839#endif // wxUSE_TOOLBAR
1c4f8f8d
VZ
840
841#if wxUSE_STATUSBAR
2d120f83 842 PositionStatusBar();
1c4f8f8d
VZ
843#endif // wxUSE_STATUSBAR
844
2d120f83 845 return TRUE;
4bb6408c
JS
846}
847
50414e24
JS
848WXWidget wxFrame::GetClientWidget() const
849{
2d120f83 850 return m_clientArea;
50414e24
JS
851}
852
af111fc3 853void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize))
0d57be45
JS
854{
855 // TODO
856}
857
858void wxFrame::ChangeBackgroundColour()
859{
621793f4
JS
860 if (GetClientWidget())
861 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
0d57be45
JS
862}
863
864void wxFrame::ChangeForegroundColour()
865{
621793f4
JS
866 if (GetClientWidget())
867 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
0d57be45
JS
868}
869
af111fc3 870void wxCloseFrameCallback(Widget WXUNUSED(widget), XtPointer client_data, XmAnyCallbackStruct *WXUNUSED(cbs))
4bb6408c 871{
2d120f83 872 wxFrame *frame = (wxFrame *)client_data;
dfe1eee3 873
2d120f83
JS
874 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId());
875 closeEvent.SetEventObject(frame);
dfe1eee3 876
2d120f83
JS
877 // May delete the frame (with delayed deletion)
878 frame->GetEventHandler()->ProcessEvent(closeEvent);
4bb6408c 879}
0d57be45 880
dc1efb1d
JS
881static void wxFrameEventHandler(Widget wid,
882 XtPointer WXUNUSED(client_data),
883 XEvent* event,
884 Boolean* continueToDispatch)
885{
886 wxFrame *frame = (wxFrame *)wxGetWindowFromTable(wid);
887 if (frame)
888 {
889 wxMouseEvent wxevent(wxEVT_NULL);
890 if (wxTranslateMouseEvent(wxevent, frame, wid, event))
891 {
892 wxevent.SetEventObject(frame);
893 wxevent.SetId(frame->GetId());
894 frame->GetEventHandler()->ProcessEvent(wxevent);
895 }
896 else
897 {
898 // An attempt to implement OnCharHook by calling OnCharHook first;
899 // if this returns TRUE, set continueToDispatch to False
900 // (don't continue processing).
901 // Otherwise set it to True and call OnChar.
902 wxKeyEvent keyEvent(wxEVT_CHAR);
903 if (wxTranslateKeyEvent(keyEvent, frame, wid, event))
904 {
905 keyEvent.SetEventObject(frame);
906 keyEvent.SetId(frame->GetId());
907 keyEvent.SetEventType(wxEVT_CHAR_HOOK);
908 if (frame->GetEventHandler()->ProcessEvent(keyEvent))
909 {
910 *continueToDispatch = False;
911 return;
912 }
913 else
914 {
915 // For simplicity, OnKeyDown is the same as OnChar
916 // TODO: filter modifier key presses from OnChar
917 keyEvent.SetEventType(wxEVT_KEY_DOWN);
918
919 // Only process OnChar if OnKeyDown didn't swallow it
920 if (!frame->GetEventHandler()->ProcessEvent (keyEvent))
921 {
922 keyEvent.SetEventType(wxEVT_CHAR);
923 frame->GetEventHandler()->ProcessEvent(keyEvent);
924 }
925 }
926 }
927 }
928 }
929 *continueToDispatch = True;
930}