1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/frame.cpp
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
31 #include "wx/settings.h"
32 #include "wx/toolbar.h"
33 #include "wx/statusbr.h"
37 #pragma message disable nosimpint
40 #if defined(__ultrix) || defined(__sgi)
45 #include <X11/Shell.h>
52 #include <Xm/MwmUtil.h>
53 #include <Xm/BulletinB.h>
56 #include <Xm/RowColumn.h>
58 #include <Xm/AtomMgr.h>
59 #include <Xm/LabelG.h>
62 #include <Xm/Protocols.h>
66 #pragma message enable nosimpint
69 #include "wx/motif/private.h"
70 #include "wx/unix/utilsx11.h"
72 // ----------------------------------------------------------------------------
74 // ----------------------------------------------------------------------------
76 static void wxFrameMapProc(Widget frameShell
, XtPointer clientData
,
77 XCrossingEvent
* event
);
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 extern wxList wxModelessWindows
;
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
89 BEGIN_EVENT_TABLE(wxFrame
, wxFrameBase
)
90 EVT_ACTIVATE(wxFrame::OnActivate
)
91 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
)
94 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
96 // ============================================================================
98 // ============================================================================
100 // ----------------------------------------------------------------------------
101 // frame construction
102 // ----------------------------------------------------------------------------
109 m_frameShell
= (WXWidget
) NULL
;
110 m_mainWidget
= (WXWidget
) NULL
;
111 m_workArea
= (WXWidget
) NULL
;
112 m_clientArea
= (WXWidget
) NULL
;
115 bool wxFrame::Create(wxWindow
*parent
,
117 const wxString
& title
,
121 const wxString
& name
)
123 if( !wxTopLevelWindow::Create( parent
, id
, title
, pos
, size
, style
,
127 int x
= pos
.x
, y
= pos
.y
;
128 int width
= size
.x
, height
= size
.y
;
130 // Set reasonable values for position and size if defaults have been
133 // MB TODO: something better than these arbitrary values ?
134 // VZ should use X resources for this...
140 int displayW
, displayH
;
141 wxDisplaySize( &displayW
, &displayH
);
145 x
= (displayW
- width
) / 2;
150 y
= (displayH
- height
) / 2;
156 wxLogTrace(wxTRACE_Messages
,
157 "Created frame (0x%p) with work area 0x%p and client "
158 "area 0x%p", m_mainWidget
, m_workArea
, m_clientArea
);
160 XtAddEventHandler((Widget
) m_clientArea
, ExposureMask
,False
,
161 wxUniversalRepaintProc
, (XtPointer
) this);
164 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
166 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
168 XtVaSetValues((Widget
) m_frameShell
, XmNwidth
, width
, NULL
);
170 XtVaSetValues((Widget
) m_frameShell
, XmNheight
, height
, NULL
);
175 wxSize
newSize(width
, height
);
176 wxSizeEvent
sizeEvent(newSize
, GetId());
177 sizeEvent
.SetEventObject(this);
179 HandleWindowEvent(sizeEvent
);
184 bool wxFrame::XmDoCreateTLW(wxWindow
* WXUNUSED(parent
),
185 wxWindowID
WXUNUSED(id
),
186 const wxString
& WXUNUSED(title
),
187 const wxPoint
& WXUNUSED(pos
),
188 const wxSize
& WXUNUSED(size
),
190 const wxString
& name
)
194 frameShell
= XtCreatePopupShell( name
, topLevelShellWidgetClass
,
195 (Widget
)wxTheApp
->GetTopLevelWidget(),
198 XtVaSetValues(frameShell
,
199 // Allows menu to resize
200 XmNallowShellResize
, True
,
201 XmNdeleteResponse
, XmDO_NOTHING
,
202 XmNmappedWhenManaged
, False
,
203 XmNiconic
, (style
& wxICONIZE
) ? True
: False
,
206 m_frameShell
= (WXWidget
)frameShell
;
208 m_mainWidget
= (WXWidget
) XtVaCreateManagedWidget("main_window",
209 xmMainWindowWidgetClass
, frameShell
,
210 XmNresizePolicy
, XmRESIZE_NONE
,
213 m_workArea
= (WXWidget
) XtVaCreateWidget("form",
214 xmFormWidgetClass
, (Widget
) m_mainWidget
,
215 XmNresizePolicy
, XmRESIZE_NONE
,
218 m_clientArea
= (WXWidget
) XtVaCreateWidget("client",
219 xmBulletinBoardWidgetClass
, (Widget
) m_workArea
,
222 XmNrightAttachment
, XmATTACH_FORM
,
223 XmNleftAttachment
, XmATTACH_FORM
,
224 XmNtopAttachment
, XmATTACH_FORM
,
225 XmNbottomAttachment
, XmATTACH_FORM
,
228 XtVaSetValues((Widget
) m_mainWidget
,
229 XmNworkWindow
, (Widget
) m_workArea
,
232 XtManageChild((Widget
) m_clientArea
);
233 XtManageChild((Widget
) m_workArea
);
235 XtTranslations ptr
= XtParseTranslationTable( "<Configure>: resize()" );
236 XtOverrideTranslations( (Widget
) m_workArea
, ptr
);
237 XtFree( (char *)ptr
);
239 /* Part of show-&-hide fix */
240 XtAddEventHandler( frameShell
, StructureNotifyMask
,
241 False
, (XtEventHandler
)wxFrameMapProc
,
244 XtRealizeWidget(frameShell
);
246 wxAddWindowToTable( (Widget
)m_workArea
, this);
247 wxAddWindowToTable( (Widget
)m_clientArea
, this);
249 wxModelessWindows
.Append( this );
260 XtRemoveEventHandler((Widget
) m_clientArea
, ExposureMask
, False
,
261 wxUniversalRepaintProc
, (XtPointer
) this);
269 m_frameMenuBar
->DestroyMenuBar();
270 delete m_frameMenuBar
;
271 m_frameMenuBar
= NULL
;
274 if (m_frameStatusBar
)
276 delete m_frameStatusBar
;
277 m_frameStatusBar
= NULL
;
282 Widget frameShell
= (Widget
)GetShellWidget();
285 XtRemoveEventHandler( frameShell
, StructureNotifyMask
,
286 False
, (XtEventHandler
)wxFrameMapProc
,
291 wxDeleteWindowFromTable( (Widget
)m_clientArea
);
292 XtDestroyWidget( (Widget
)m_clientArea
);
297 XtVaSetValues( (Widget
)m_mainWidget
,
298 XmNworkWindow
, (Widget
)NULL
,
301 wxDeleteWindowFromTable( (Widget
)m_workArea
);
302 XtDestroyWidget( (Widget
)m_workArea
);
306 XtDestroyWidget( (Widget
)m_mainWidget
);
309 XtDestroyWidget( frameShell
);
312 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
313 void wxFrame::DoGetClientSize(int *x
, int *y
) const
316 XtVaGetValues((Widget
) m_workArea
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
318 if (m_frameStatusBar
)
321 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
322 yy
= (Dimension
)(yy
- sbh
);
328 m_frameToolBar
->GetSize(& tbw
, & tbh
);
329 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
330 xx
= (Dimension
)(xx
- tbw
);
332 yy
= (Dimension
)(yy
- tbh
);
334 #endif // wxUSE_TOOLBAR
336 //CE found a call here with NULL y pointer
343 // Set the client size (i.e. leave the calculation of borders etc.
345 void wxFrame::DoSetClientSize(int width
, int height
)
347 // Calculate how large the new main window should be
348 // by finding the difference between the client area and the
349 // main window area, and adding on to the new client area
351 XtVaSetValues((Widget
) m_workArea
, XmNwidth
, width
, NULL
);
355 if (m_frameStatusBar
)
358 m_frameStatusBar
->GetSize(& sbw
, & sbh
);
365 m_frameToolBar
->GetSize(& tbw
, & tbh
);
366 if (m_frameToolBar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
371 #endif // wxUSE_TOOLBAR
373 XtVaSetValues((Widget
) m_workArea
, XmNheight
, height
, NULL
);
377 wxSize
newSize(width
, height
);
378 wxSizeEvent
sizeEvent(newSize
, GetId());
379 sizeEvent
.SetEventObject(this);
381 HandleWindowEvent(sizeEvent
);
385 void wxFrame::DoGetSize(int *width
, int *height
) const
389 *width
= -1; *height
= -1;
394 XtVaGetValues((Widget
) m_frameShell
, XmNwidth
, &xx
, XmNheight
, &yy
, NULL
);
395 *width
= xx
; *height
= yy
;
398 void wxFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
))
401 XtVaSetValues((Widget
) m_frameShell
, XmNx
, x
, NULL
);
403 XtVaSetValues((Widget
) m_frameShell
, XmNy
, y
, NULL
);
405 XtVaSetValues((Widget
) m_mainWidget
, XmNwidth
, width
, NULL
);
407 XtVaSetValues((Widget
) m_mainWidget
, XmNheight
, height
, NULL
);
409 if (!(height
== -1 && width
== -1))
415 bool wxFrame::Show( bool show
)
417 if( !wxWindowBase::Show( show
) )
422 Widget shell
= (Widget
)GetShellWidget();
424 return wxWindow::Show(show
);
426 SetVisibleStatus(show
);
429 XtPopup(shell
, XtGrabNone
);
439 void wxFrame::SetTitle(const wxString
& title
)
441 wxString oldTitle
= GetTitle();
442 if( title
== oldTitle
)
445 wxTopLevelWindow::SetTitle( title
);
448 XtVaSetValues( (Widget
)m_frameShell
,
449 XmNtitle
, (const char*)title
.mb_str(),
450 XmNiconName
, (const char*)title
.mb_str(),
454 void wxFrame::DoSetIcon(const wxIcon
& icon
)
459 if (!icon
.Ok() || !icon
.GetDrawable())
462 XtVaSetValues((Widget
) m_frameShell
,
463 XtNiconPixmap
, icon
.GetDrawable(),
467 void wxFrame::SetIcons(const wxIconBundle
& icons
)
469 wxFrameBase::SetIcons( icons
);
474 DoSetIcon( m_icons
.GetIcon( -1 ) );
475 wxSetIconsX11(GetXDisplay(),
476 (WXWindow
) XtWindow( (Widget
) m_frameShell
), icons
);
479 void wxFrame::PositionStatusBar()
481 if (!m_frameStatusBar
)
485 GetClientSize(&w
, &h
);
487 m_frameStatusBar
->GetSize(&sw
, &sh
);
489 // Since we wish the status bar to be directly under the client area,
490 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
491 m_frameStatusBar
->SetSize(0, h
, w
, sh
);
494 WXWidget
wxFrame::GetMenuBarWidget() const
497 return GetMenuBar()->GetMainWidget();
499 return (WXWidget
) NULL
;
502 void wxFrame::SetMenuBar(wxMenuBar
*menuBar
)
506 m_frameMenuBar
= NULL
;
510 // Currently can't set it twice
511 // wxASSERT_MSG( (m_frameMenuBar == NULL), "Cannot set the menubar more than once");
515 m_frameMenuBar
->DestroyMenuBar();
516 delete m_frameMenuBar
;
519 m_frameMenuBar
= menuBar
;
520 m_frameMenuBar
->CreateMenuBar(this);
523 // Responds to colour changes, and passes event on to children.
524 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
526 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
529 if ( m_frameStatusBar
)
531 wxSysColourChangedEvent event2
;
532 event2
.SetEventObject( m_frameStatusBar
);
533 m_frameStatusBar
->HandleWindowEvent(event2
);
536 // Propagate the event to the non-top-level children
537 wxWindow::OnSysColourChanged(event
);
540 // Default activation behaviour - set the focus for the first child
542 void wxFrame::OnActivate(wxActivateEvent
& event
)
544 if (!event
.GetActive())
547 for(wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
;
548 node
= node
->GetNext())
550 // Find a child that's a subwindow, but not a dialog box.
551 wxWindow
*child
= node
->GetData();
552 if (!child
->IsTopLevel())
562 wxToolBar
* wxFrame::CreateToolBar(long style
,
564 const wxString
& name
)
566 if ( wxFrameBase::CreateToolBar(style
, id
, name
) )
571 return m_frameToolBar
;
574 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
576 wxFrameBase::SetToolBar(toolbar
);
580 void wxFrame::PositionToolBar()
582 wxToolBar
* tb
= GetToolBar();
586 GetClientSize(& cw
, &ch
);
589 tb
->GetSize(& tw
, & th
);
591 if (tb
->GetWindowStyleFlag() & wxTB_VERTICAL
)
593 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
594 // means, pretend we don't have toolbar/status bar, so we
595 // have the original client size.
600 // Use the 'real' position
604 tb
->SetSize(0, 0, -1, -1, wxSIZE_NO_ADJUSTMENTS
);
607 #endif // wxUSE_TOOLBAR
610 bool wxFrame::PreResize()
614 #endif // wxUSE_TOOLBAR
618 #endif // wxUSE_STATUSBAR
623 WXWidget
wxFrame::GetClientWidget() const
628 void wxFrame::ChangeFont(bool WXUNUSED(keepOriginalSize
))
633 void wxFrame::ChangeBackgroundColour()
635 if (GetClientWidget())
636 wxDoChangeBackgroundColour(GetClientWidget(), m_backgroundColour
);
639 void wxFrame::ChangeForegroundColour()
641 if (GetClientWidget())
642 wxDoChangeForegroundColour(GetClientWidget(), m_foregroundColour
);
645 /* MATTEW: Used to insure that hide-&-show within an event cycle works */
646 static void wxFrameMapProc( Widget frameShell
, XtPointer clientData
,
647 XCrossingEvent
* event
)
649 wxFrame
*tli
= (wxFrame
*)clientData
;
651 XEvent
*e
= (XEvent
*)event
;
653 if( e
->xany
.type
== MapNotify
)
656 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)False
, NULL
);
657 if( !tli
->GetVisibleStatus() )
659 /* We really wanted this to be hidden! */
660 XtUnmapWidget( frameShell
);
663 else if( e
->xany
.type
== UnmapNotify
)
665 XtVaSetValues( frameShell
, XmNiconic
, (Boolean
)True
, NULL
);